![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /usr/share/boost-build/src/util/ |
Upload File : |
# 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 formatted text echoed to the console (the default); # "text" is formatted 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 ?= ; # 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. # .option-description = Help Options ; # 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 ; if $(super-name) { $(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 " b2 [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 Suppress all informational messages" ; print.list-item "-q Stop at first error" ; print.list-item "--reconfigure Rerun all configuration checks" ; 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.Build Usage" "b2 [ 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 b2. ; print.list-item --x\; Any option not explicitly handled by Boost.Build remains available to build scripts using the '"ARGV"' variable. ; print.list-item --abbreviate-paths\; Use abbreviated paths for targets. ; print.list-item --hash\; Shorten target paths by using an MD5 hash. ; print.list-item -dconsole\; Run the interactive debugger. Cannot be used with any other option. ; 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 module given # with the name `module-name` of the form ".option.*". # local rule print-help-options ( module-name ) { local options-to-list = [ MATCH "^[.]option[.](.*)" : $($(module-name).variables) ] ; if $(options-to-list) { local option-title = $($(module-name)..option-description.initial) ; if ! $(option-title) || $(option-title) = "(empty)" { option-title = "$(module-name) Options" ; } local option-description = $(option-title) $($(module-name)..option-description.docs) ; print.section $(option-description) ; print.list-start ; for local option in [ sequence.insertion-sort $(options-to-list) ] { local def = disabled ; if $($(module-name)..option.$(option).default) != "(empty)" { def = $($(module-name)..option.$(option).default) ; } 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) && $($(module-name).$(rule-name).args.$($(module-name).$(rule-name).args).docs) { print.list-start ; for local arg-name in $($(module-name).$(rule-name).args) { if $($(module-name).$(rule-name).args.$(arg-name).docs) { 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 = "\t " ; # Extract the text from a single comment # local rule extract-one-comment ( var # The name of the variable to extract from : start # The initial part after the leading '#' ) { local m = [ MATCH ^(\\|)(.*) : $(start) ] ; if $(m) { start = $(m[2]) ; local comment ; while true { local end = [ MATCH "(.*)(\\|#)(.*)" : $(start) ] ; if $(end) { comment += $(end[1]) ; $(var) = $(end[3]) $($(var)[2-]) ; return $(comment) ; } else { comment += $(start) ; $(var) = $($(var)[2-]) ; } start = $($(var)[1]) ; } } else { $(var) = $($(var)[2-]) ; if $(start) { return [ MATCH "^[$(ws)]?(.*)$" : $(start) ] ; } else { return "" ; } } } # 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)) { comment += [ extract-one-comment $(var) : $(l[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) { 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) && $($(var)) { 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. : var # The name of the variable to extract from. ) { # [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" { # Scan within this class scope. local scope-level = [ extract-token $(var) ] ; local scope-name = $(class-parts[2]) ; while $(scope-level) && $($(var)) { 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-]) ; } } # This has to come after parsing the rules, because # it looks up the rules for the class from the global list. set-class-doc $(class-parts[2]) $(module-name) : $(class-parts[3]) ; return true ; } } # 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) : text ] { } 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 << = "([^\r\n]*)[\r]?[\n](.*)" ; 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) ; }