mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 13:22:11 +00:00
* util/print.jam: Do not quote the argument to the 'echo' command on windows. It's special, and does not need quotes. Adding them will cause the quotes to always appear in the output, which would be different behaviour from Unix. * tools/common.jam (response-file): Add quotes here. [SVN r26836]
468 lines
14 KiB
Plaintext
468 lines
14 KiB
Plaintext
# (C) Copyright Rene Rivera, 2002-2003.
|
|
#
|
|
# See accompanying license for terms and conditions of use.
|
|
#
|
|
|
|
# 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 ;
|
|
|
|
# The current output target. Defaults to console.
|
|
output-target = console ;
|
|
|
|
# The current output type. Defaults to plain.
|
|
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. If not set
|
|
# it defaults to 'console' indicating immediate display to the console.
|
|
# Other possible values are: 'html-file'.
|
|
#
|
|
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. If not set
|
|
# it defaults to 'console' indicating immediate display to the console.
|
|
# Other possible values are: 'html-file'.
|
|
#
|
|
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. If not set
|
|
# it defaults to 'console' indicating immediate display to the console.
|
|
# Other possible values are: 'html-file'.
|
|
#
|
|
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. If not set
|
|
# it defaults to 'console' indicating immediate display to the console.
|
|
# Other possible values are: 'html-file'.
|
|
#
|
|
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 = ; }
|
|
else if $(c) = " " { c = ; }
|
|
indent = $(indent)$(c) ;
|
|
}
|
|
local html-text = [ escape-html $(text) : ] ;
|
|
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
|
|
{
|
|
while $(strings)
|
|
{
|
|
ECHO $(strings[1]) ;
|
|
strings = $(strings[2-]) ;
|
|
}
|
|
}
|
|
}
|
|
# We ignore empty output because the Windows ECHO command is
|
|
# braindamaged. It doesn't have any facility for echoing a blank line.
|
|
else if $(output-target)
|
|
{
|
|
if ! $($(output-target).did-action)
|
|
{
|
|
$(output-target).did-action = yes ;
|
|
_ on $(output-target) = " " ;
|
|
nl on $(output-target) = "
|
|
" ;
|
|
text-redirect-0 on $(output-target) = ">>" ;
|
|
text-redirect-n on $(output-target) = ">>" ;
|
|
text-front on $(output-target) = ;
|
|
text-prefix on $(output-target) = ;
|
|
text-body on $(output-target) = ;
|
|
text-suffix on $(output-target) = ;
|
|
text-action $(output-target) ;
|
|
text-front-section.$(soutput-target) = ;
|
|
}
|
|
if $(overwrite)
|
|
{
|
|
text-redirect-0 on $(output-target) = ">" ;
|
|
}
|
|
if ! $(text-front-section.$(output-target))
|
|
{
|
|
text-front on $(output-target) = [ echo-cmd $(strings[1]) ] ;
|
|
text-front-section.$(output-target) = $(prefix-body-suffix) ;
|
|
strings = $(strings[2-]) ;
|
|
}
|
|
if $(strings)
|
|
{
|
|
if ( $(prefix-body-suffix) = prefix &&
|
|
$(text-front-section.$(output-target)) != prefix ) ||
|
|
( $(prefix-body-suffix) = body &&
|
|
$(text-front-section.$(output-target)) = suffix )
|
|
{
|
|
text-$(text-front-section.$(output-target)) on $(output-target) =
|
|
[ on $(output-target) return $(text-front) ]
|
|
[ on $(output-target) return $(text-$(text-front-section.$(output-target))) ] ;
|
|
text-front on $(output-target) = [ echo-cmd $(strings[1]) ] ;
|
|
text-front-section.$(output-target) = $(prefix-body-suffix) ;
|
|
strings = $(strings[2-]) ;
|
|
}
|
|
while $(strings)
|
|
{
|
|
text-$(prefix-body-suffix) on $(output-target) += [ echo-cmd $(strings[1]) ] ;
|
|
strings = $(strings[2-]) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
# 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) "&" "&" ] ;
|
|
html = [ regex.replace $(html) "<" "<" ] ;
|
|
html = [ regex.replace $(html) ">" ">" ] ;
|
|
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
|
|
{
|
|
$(text-front)$(_)$(text-redirect-0)$(_)"$(<)"
|
|
$(text-prefix)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
|
|
$(text-body)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
|
|
$(text-suffix)$(_)$(text-redirect-n)$(_)"$(<)"$(nl)
|
|
}
|
|
|
|
if [ modules.peek : NT ]
|
|
{
|
|
rule echo-cmd ( string ? )
|
|
{
|
|
if $(string) || $(string) != ""
|
|
{
|
|
local escaped = [ regex.escape $(string) : "&|()<>^" : "^" ] ;
|
|
return "echo $(escaped)" ;
|
|
}
|
|
else
|
|
{
|
|
return "echo." ;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rule echo-cmd ( string ? )
|
|
{
|
|
if $(string) || $(string) != ""
|
|
{
|
|
local escaped = [ regex.escape $(string) : "\\\"" : "\\" ] ;
|
|
return "echo \"$(escaped)\"" ;
|
|
}
|
|
else
|
|
{
|
|
return "echo" ;
|
|
}
|
|
}
|
|
}
|
|
|
|
local 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 two three" "&<>" :
|
|
# escape-html "one two three" "&<>" ;
|
|
}
|