# 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 handle generation of documentation # from BoostBook sources. import class : class new ; import common ; import errors ; import targets ; import feature ; import generators ; import property ; import property-set ; import regex ; import scanner ; feature.feature xsl:param : : free ; feature.feature format : html onehtml man pdf ps docbook fo : incidental implicit composite ; type.register XML : xml ; type.register DOCBOOK : docbook ; type.register HTML : html ; type.register FO : fo ; type.register PDF : pdf ; type.register PS : ps ; type.register XSLT : xsl ; type.register HTMLDIR ; type.register MANPAGES ; # Generates handle -> * rules a bit strangely, so don't try to use them for now #generators.register-standard boostbook.xslt : XML XSLT : * ; generators.register-standard boostbook.boostbook-to-docbook : XML : DOCBOOK ; generators.register-standard boostbook.docbook-to-onehtml : DOCBOOK : HTML ; generators.register-standard boostbook.docbook-to-htmldir : DOCBOOK : HTMLDIR ; generators.register-standard boostbook.docbook-to-manpages : DOCBOOK : MANPAGES ; generators.register-standard boostbook.docbook-to-fo : DOCBOOK : FO ; # Initialize BoostBook support. The parameters are: # docbook-xsl-dir: The DocBook XSL stylesheet directory. If not provided, # we use DOCBOOK_XSL_DIR from the environment (if available). 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). Otherwise, we let # the XML processor load the DTD remotely. # # boostbook-xsl-dir: The BoostBook XSL stylesheet directory. If not provided, # we use $(BOOST_ROOT)/tools/boostbook/xsl (the default location). # # boostbook-dtd-dir: The BoostBook DTD directory. If not provided, we use # $(BOOST_ROOT)/tools/boostbook/dtd (the default location). rule init ( docbook-xsl-dir ? : docbook-dtd-dir ? : boostbook-xsl-dir ? : boostbook-dtd-dir ? ) { if ! $(docbook-xsl-dir) { docbook-xsl-dir = [ modules.peek : DOCBOOK_XSL_DIR ] ; } if ! $(docbook-dtd-dir) { docbook-dtd-dir = [ modules.peek : DOCBOOK_DTD_DIR ] ; } if ! $(boostbook-xsl-dir) { boostbook-xsl-dir = [ modules.peek : BOOST_ROOT ] ; boostbook-xsl-dir = $(boostbook-xsl-dir)/tools/boostbook/xsl ; } if ! $(boostbook-dtd-dir) { boostbook-dtd-dir = [ modules.peek : BOOST_ROOT ] ; boostbook-dtd-dir = $(boostbook-dtd-dir)/tools/boostbook/dtd ; } if ! $(.initialized) { $(.initialized) = true ; .docbook-xsl-dir = $(docbook-xsl-dir) ; .docbook-dtd-dir = $(docbook-dtd-dir) ; .boostbook-xsl-dir = $(boostbook-xsl-dir) ; .boostbook-dtd-dir = $(boostbook-dtd-dir) ; } } rule xslt ( target : source stylesheet : properties * ) { local flags ; for local param in [ feature.get-values : $(properties) ] { local namevalue = [ regex.split $(param) "=" ] ; flags += --stringparam $(namevalue[1]) $(namevalue[2]) ; } STYLESHEET on $(target) = $(stylesheet) ; FLAGS on $(target) = $(flags) ; xslt-xsltproc $(target) : $(source) ; } rule xslt-dir ( target : source stylesheet : properties * : dirname ) { local flags ; for local param in [ feature.get-values : $(properties) ] { local namevalue = [ regex.split $(param) "=" ] ; flags += --stringparam $(namevalue[1]) $(namevalue[2]) ; } STYLESHEET on $(target) = $(stylesheet) ; FLAGS on $(target) = $(flags) ; DIRECTORY on $(target) = $(dirname) ; xslt-xsltproc-dir $(target) : $(source) ; } rule boostbook-to-docbook ( target : source : properties * ) { xslt $(target) : $(source) "$(.boostbook-xsl-dir)/docbook.xsl" : $(properties) ; } rule docbook-to-onehtml ( target : source : properties * ) { xslt $(target) : $(source) "$(.boostbook-xsl-dir)/html-single.xsl" : $(properties) ; } rule docbook-to-htmldir ( target : source : properties * ) { xslt-dir $(target) : $(source) "$(.boostbook-xsl-dir)/html.xsl" : $(properties) : html ; } rule docbook-to-manpages ( target : source : properties * ) { xslt-dir $(target) : $(source) "$(.boostbook-xsl-dir)/manpages.xsl" : $(properties) : man ; } rule docbook-to-fo ( target : source : properties * ) { xslt $(target) : $(source) "$(.boostbook-xsl-dir)/fo.xsl" : $(properties) ; } rule xml-catalog-action ( target : property-set ? : catalog-entries * ) { action.__init__ $(target) : : generate-xml-catalog : $(property-set) ; self.docbook-xsl-dir = [ feature.get-values : $(catalog-entries) ] ; self.docbook-dtd-dir = [ feature.get-values : $(catalog-entries) ] ; self.boostbook-dtd-dir = [ feature.get-values : $(catalog-entries) ] ; rule actualize ( ) { if ! $(self.actualized) { self.actualized = true ; local actual = [ $(self.targets[1]).actualize ] ; local text = "" ; local rewrites ; # BoostBook DTD catalog entry rewrites += "" ; if ! $(self.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 { rewrites += "" ; } if ! $(self.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 { rewrites += "" ; } REWRITES on $(actual) = $(rewrites) ; ALWAYS $(actual) ; boostbook.write-xml-catalog $(actual) ; } } } class xml-catalog-action : action ; actions quietly write-xml-catalog { echo "" > $(<) ; echo "> $(<) ; echo " PUBLIC \"-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN\"" >> $(<) ; echo " \"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd\">" >> $(<) ; echo "" >> $(<) ; echo "$(REWRITES)" >> $(<) ; echo "" >> $(<) ; } rule boostbook-target-class ( name : project : sources * : requirements * : default-build * : catalog-entries * ) { basic-target.__init__ $(name) : $(project) : $(sources) : $(requirements) : $(default-build) ; self.catalog-entries = $(catalog-entries) ; rule construct ( source-targets * : property-set ) { local path = [ project.attribute $(self.project) location ] ; local catalog = [ new file-target catalog : XML : $(self.project) ] ; $(catalog).action [ new xml-catalog-action $(catalog) : $(property-set) : $(self.catalog-entries) ] ; $(catalog).set-path $(path) ; catalog = [ virtual-target.register $(catalog) ] ; local properties = [ $(property-set).raw ] ; local format = [ feature.get-values : $(properties) ] ; local targets = $(catalog) ; local type = none ; local manifest ; switch $(format) { case html : { type = HTMLDIR ; 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 ; } if $(manifest) { for local i in $(source-targets) { local base-target = [ generators.construct $(self.project) : DOCBOOK : $(property-set) : $(i) ] ; $(base-target).depends $(catalog) ; local target = [ generators.construct $(self.project) $(manifest) : $(type) : $(property-set) : $(base-target) ] ; $(target).set-path $(format) ; targets += $(target) ; } } else { for local i in $(source-targets) { local target = [ generators.construct $(self.project) : $(type) : $(property-set) : $(i) ] ; if ! $(target) { errors.error "Cannot build documentation type '$(format)'" ; } else { $(target).depends $(catalog) ; targets += $(target) ; } } } return $(targets) ; } } class boostbook-target-class : basic-target ; rule boostbook ( target-name : source : requirements * : default-build * ) { local project = [ CALLER_MODULE ] ; targets.main-target-alternative [ new boostbook-target-class $(target-name) : $(project) : $(source) : [ targets.main-target-requirements $(requirements) : $(project) ] : [ targets.main-target-default-build $(default-build) : $(project) ] : $(.docbook-xsl-dir) $(.docbook-dtd-dir) $(.boostbook-dtd-dir) ] ; } actions xslt-xsltproc { XML_CATALOG_FILES=catalog.xml xsltproc $(FLAGS) --xinclude -o $(<) $(STYLESHEET) $(>) } actions xslt-xsltproc-dir { XML_CATALOG_FILES=catalog.xml xsltproc $(FLAGS) --xinclude -o $(DIRECTORY)/ $(STYLESHEET) $(>) } ############################################################################# # XML Catalog Generation ############################################################################# # 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. rule xinclude-scanner ( includes * ) { scanner.__init__ ; rule pattern ( ) { return "xi:include[ ]*href=\"([^\"]*)\"" ; } rule process ( target : matches * ) { local target_path = [ path.native [ path.parent [ path.make [ virtual-target.binding $(target) ] ] ] ] ; for local i in $(matches) { local i2 = [ SEARCH_FOR_TARGET $(i) : $(target_path) ] ; INCLUDES $(target) : $(i2) ; } BINDRULE on $(matches) = virtual-target.remember-binding ; for local j in $(matches) { scanner.install $(__name__) : $(j) : $(target) ; } } } class xinclude-scanner : scanner ; scanner.register xinclude-scanner ; type.set-scanner XML : xinclude-scanner ;