summaryrefslogtreecommitdiff
path: root/autosetup/autosetup
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2019-11-20 20:30:03 +0100
committerDidier Raboud <odyx@debian.org>2019-11-20 20:30:03 +0100
commitb0aeaea912817dd53fda33331a8f6e562b695a50 (patch)
tree4c3eca617f759c0bc9698cc35c599ef3113fa706 /autosetup/autosetup
parent68b3a623cde64e8dd53f8b1929a7cc9eabf0dadd (diff)
parent052cee686ea886c16b59dcabb5a04b2e6d390ade (diff)
Update to upstream 0.79+dfsg0
[git-debrebase anchor: new upstream 0.79+dfsg0, merge]
Diffstat (limited to 'autosetup/autosetup')
-rwxr-xr-xautosetup/autosetup1081
1 files changed, 802 insertions, 279 deletions
diff --git a/autosetup/autosetup b/autosetup/autosetup
index 84886c2..da3a835 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -3,12 +3,13 @@
# All rights reserved
# vim:se syntax=tcl:
# \
-dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"
+dir=`dirname "$0"`; exec "`$dir/autosetup-find-tclsh`" "$0" "$@"
-set autosetup(version) 0.6.5
+# Note that the version has a trailing + on unreleased versions
+set autosetup(version) 0.6.9
# Can be set to 1 to debug early-init problems
-set autosetup(debug) 0
+set autosetup(debug) [expr {"--debug" in $argv}]
##################################################################
#
@@ -61,7 +62,7 @@ proc main {argv} {
set autosetup(srcdir) [pwd]
} else {
# Invoked via the configure wrapper
- set autosetup(srcdir) [file dirname $autosetup(exe)]
+ set autosetup(srcdir) [file-normalize [file dirname $autosetup(exe)]]
}
set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def]
@@ -70,23 +71,47 @@ proc main {argv} {
set autosetup(argv) $argv
set autosetup(cmdline) {}
+ # options is a list of known options
set autosetup(options) {}
+ # optset is a dictionary of option values set by the user based on getopt
+ set autosetup(optset) {}
+ # optdefault is a dictionary of default values
+ set autosetup(optdefault) {}
+ # options-defaults is a dictionary of overrides for default values for options
+ set autosetup(options-defaults) {}
set autosetup(optionhelp) {}
set autosetup(showhelp) 0
+ use util
+
# Parse options
use getopt
- array set ::useropts [getopt argv]
+ # At the is point we don't know what is a valid option
+ # We simply parse anything that looks like an option
+ set autosetup(getopt) [getopt argv]
#"=Core Options:"
options-add {
help:=local => "display help and options. Optionally specify a module name, such as --help=system"
+ licence license => "display the autosetup license"
version => "display the version of autosetup"
ref:=text manual:=text
reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
debug => "display debugging output as autosetup runs"
- install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
+ install:=. => "install autosetup to the current or given directory"
+ }
+ if {$autosetup(installed)} {
+ # hidden options so we can produce a nice error
+ options-add {
+ sysinstall:path
+ }
+ } else {
+ options-add {
+ sysinstall:path => "install standalone autosetup to the given directory (e.g.: /usr/local)"
+ }
+ }
+ options-add {
force init:=help => "create initial auto.def, etc. Use --init=help for known types"
# Undocumented options
option-checking=1
@@ -96,15 +121,14 @@ proc main {argv} {
conf:
}
- #parray ::useropts
if {[opt-bool version]} {
puts $autosetup(version)
exit 0
}
# autosetup --conf=alternate-auto.def
- if {[opt-val conf] ne ""} {
- set autosetup(autodef) [opt-val conf]
+ if {[opt-str conf o]} {
+ set autosetup(autodef) $o
}
# Debugging output (set this early)
@@ -120,38 +144,47 @@ proc main {argv} {
}
# Now any auto-load modules
- foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
- automf_load source $file
- }
+ autosetup_load_auto_modules
- if {[opt-val help] ne ""} {
+ if {[opt-str help o]} {
incr autosetup(showhelp)
use help
- autosetup_help [opt-val help]
+ autosetup_help $o
}
- if {[opt-val {manual ref reference}] ne ""} {
+ if {[opt-bool licence license]} {
use help
- autosetup_reference [opt-val {manual ref reference}]
+ autosetup_show_license
+ exit 0
+ }
+
+ if {[opt-str {manual ref reference} o]} {
+ use help
+ autosetup_reference $o
}
# Allow combining --install and --init
set earlyexit 0
- if {[opt-val install] ne ""} {
+ if {[opt-str install o]} {
use install
- autosetup_install [opt-val install]
+ autosetup_install $o
incr earlyexit
}
- if {[opt-val init] ne ""} {
+ if {[opt-str init o]} {
use init
- autosetup_init [opt-val init]
+ autosetup_init $o
incr earlyexit
}
if {$earlyexit} {
exit 0
}
+ if {[opt-str sysinstall o]} {
+ use install
+ autosetup_install $o 1
+ exit 0
+ }
if {![file exists $autosetup(autodef)]} {
# Check for invalid option first
@@ -181,6 +214,7 @@ proc main {argv} {
# Log how we were invoked
configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
+ configlog "Tclsh: [info nameofexecutable]"
# Note that auto.def is *not* loaded in the global scope
source $autosetup(autodef)
@@ -200,30 +234,134 @@ proc main {argv} {
exit 0
}
-# @opt-bool option ...
+# @opt-bool ?-nodefault? option ...
+#
+# Check each of the named, boolean options and if any have been explicitly enabled
+# or disabled by the user, return 1 or 0 accordingly.
+#
+# If the option was specified more than once, the last value wins.
+# e.g. With '--enable-foo --disable-foo', '[opt-bool foo]' will return 0
#
-# Check each of the named, boolean options and return 1 if any of them have
-# been set by the user.
+# If no value was specified by the user, returns the default value for the
+# first option. If '-nodefault' is given, this behaviour changes and
+# -1 is returned instead.
#
proc opt-bool {args} {
+ set nodefault 0
+ if {[lindex $args 0] eq "-nodefault"} {
+ set nodefault 1
+ set args [lrange $args 1 end]
+ }
option-check-names {*}$args
- opt_bool ::useropts {*}$args
+
+ foreach opt $args {
+ if {[dict exists $::autosetup(optset) $opt]} {
+ return [dict get $::autosetup(optset) $opt]
+ }
+ }
+
+ if {$nodefault} {
+ return -1
+ }
+ # Default value is the default for the first option
+ return [dict get $::autosetup(optdefault) [lindex $args 0]]
}
-# @opt-val option-list ?default=""?
+# @opt-val optionlist ?default=""?
#
-# Returns a list containing all the values given for the non-boolean options in 'option-list'.
+# Returns a list containing all the values given for the non-boolean options in '$optionlist'.
# There will be one entry in the list for each option given by the user, including if the
# same option was used multiple times.
-# If only a single value is required, use something like:
#
-## lindex [opt-val $names] end
+# If no options were set, '$default' is returned (exactly, not as a list).
#
-# If no options were set, $default is returned (exactly, not as a list).
+# Note: For most use cases, 'opt-str' should be preferred.
#
proc opt-val {names {default ""}} {
option-check-names {*}$names
- join [opt_val ::useropts $names $default]
+
+ foreach opt $names {
+ if {[dict exists $::autosetup(optset) $opt]} {
+ lappend result {*}[dict get $::autosetup(optset) $opt]
+ }
+ }
+ if {[info exists result]} {
+ return $result
+ }
+ return $default
+}
+
+# @opt-str optionlist varname ?default?
+#
+# Sets '$varname' in the callers scope to the value for one of the given options.
+#
+# For the list of options given in '$optionlist', if any value is set for any option,
+# the option value is taken to be the *last* value of the last option (in the order given).
+#
+# If no option was given, and a default was specified with 'options-defaults',
+# that value is used.
+#
+# If no 'options-defaults' value was given and '$default' was given, it is used.
+#
+# If none of the above provided a value, no value is set.
+#
+# The return value depends on whether '$default' was specified.
+# If it was, the option value is returned.
+# If it was not, 1 is returns if a value was set, or 0 if not.
+#
+# Typical usage is as follows:
+#
+## if {[opt-str {myopt altname} o]} {
+## do something with $o
+## }
+#
+# Or:
+## define myname [opt-str {myopt altname} o "/usr/local"]
+#
+proc opt-str {names varname args} {
+ global autosetup
+
+ option-check-names {*}$names
+ upvar $varname value
+
+ if {[llength $args]} {
+ # A default was given, so always return the string value of the option
+ set default [lindex $args 0]
+ set retopt 1
+ } else {
+ # No default, so return 0 or 1 to indicate if a value was found
+ set retopt 0
+ }
+
+ foreach opt $names {
+ if {[dict exists $::autosetup(optset) $opt]} {
+ set result [lindex [dict get $::autosetup(optset) $opt] end]
+ }
+ }
+
+ if {![info exists result]} {
+ # No user-specified value. Has options-defaults been set?
+ foreach opt $names {
+ if {[dict exists $::autosetup(options-defaults) $opt]} {
+ set result [dict get $autosetup(options-defaults) $opt]
+ }
+ }
+ }
+
+ if {[info exists result]} {
+ set value $result
+ if {$retopt} {
+ return $value
+ }
+ return 1
+ }
+
+ if {$retopt} {
+ set value $default
+ return $value
+ }
+
+ return 0
}
proc option-check-names {args} {
@@ -235,10 +373,10 @@ proc option-check-names {args} {
}
# Parse the option definition in $opts and update
-# ::useropts() and ::autosetup(optionhelp) appropriately
+# ::autosetup(setoptions) and ::autosetup(optionhelp) appropriately
#
proc options-add {opts {header ""}} {
- global useropts autosetup
+ global autosetup
# First weed out comment lines
set realopts {}
@@ -257,6 +395,7 @@ proc options-add {opts {header ""}} {
set header {}
continue
}
+ unset -nocomplain defaultvalue equal value
#puts "i=$i, opt=$opt"
regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value
@@ -275,35 +414,101 @@ proc options-add {opts {header ""}} {
# Boolean option
lappend autosetup(options) $name
- if {![info exists useropts($name)]} {
- set useropts($name) $value
+ # Check for override
+ if {[dict exists $autosetup(options-defaults) $name]} {
+ # A default was specified with options-defaults, so use it
+ set value [dict get $autosetup(options-defaults) $name]
}
+
if {$value eq "1"} {
set opthelp "--disable-$name"
} else {
set opthelp "--$name"
}
+
+ # Set the default
+ if {$value eq ""} {
+ set value 0
+ }
+ set defaultvalue $value
+ dict set autosetup(optdefault) $name $defaultvalue
+
+ if {[dict exists $autosetup(getopt) $name]} {
+ # The option was specified by the user. Look at the last value.
+ lassign [lindex [dict get $autosetup(getopt) $name] end] type setvalue
+ if {$type eq "str"} {
+ # Can we convert the value to a boolean?
+ if {$setvalue in {1 enabled yes}} {
+ set setvalue 1
+ } elseif {$setvalue in {0 disabled no}} {
+ set setvalue 0
+ } else {
+ user-error "Boolean option $name given as --$name=$setvalue"
+ }
+ }
+ dict set autosetup(optset) $name $setvalue
+ #puts "Found boolean option --$name=$setvalue"
+ }
} else {
# String option.
lappend autosetup(options) $name
- if {$equal eq "="} {
- if {[info exists useropts($name)]} {
- # If the user specified the option with no value, the value will be "1"
- # Replace with the default
- if {$useropts($name) eq "1"} {
- set useropts($name) $value
- }
+ if {$colon eq ":"} {
+ # Was ":name=default" given?
+ # If so, set $value to the display name and $defaultvalue to the default
+ # (This is the preferred way to set a default value for a string option)
+ if {[regexp {^([^=]+)=(.*)$} $value -> value defaultvalue]} {
+ dict set autosetup(optdefault) $name $defaultvalue
}
+ }
+
+ # Maybe override the default value
+ if {[dict exists $autosetup(options-defaults) $name]} {
+ # A default was specified with options-defaults, so use it
+ set defaultvalue [dict get $autosetup(options-defaults) $name]
+ dict set autosetup(optdefault) $name $defaultvalue
+ } elseif {![info exists defaultvalue]} {
+ # For backward compatibility, if ":name" was given, use name as both
+ # the display text and the default value, but only if the user
+ # specified the option without the value
+ set defaultvalue $value
+ }
+
+ if {$equal eq "="} {
+ # String option with optional value
set opthelp "--$name?=$value?"
} else {
+ # String option with required value
set opthelp "--$name=$value"
}
+
+ # Get the values specified by the user
+ if {[dict exists $autosetup(getopt) $name]} {
+ set listvalue {}
+
+ foreach pair [dict get $autosetup(getopt) $name] {
+ lassign $pair type setvalue
+ if {$type eq "bool" && $setvalue} {
+ if {$equal ne "="} {
+ user-error "Option --$name requires a value"
+ }
+ # If given as a boolean, use the default value
+ set setvalue $defaultvalue
+ }
+ lappend listvalue $setvalue
+ }
+
+ #puts "Found string option --$name=$listvalue"
+ dict set autosetup(optset) $name $listvalue
+ }
}
# Now create the help for this option if appropriate
if {[lindex $opts $i+1] eq "=>"} {
set desc [lindex $opts $i+2]
+ if {[info exists defaultvalue]} {
+ set desc [string map [list @default@ $defaultvalue] $desc]
+ }
#string match \n* $desc
if {$header ne ""} {
lappend autosetup(optionhelp) $header ""
@@ -391,31 +596,35 @@ proc options-show {} {
}
}
-# @options options-spec
+# @options optionspec
#
# Specifies configuration-time options which may be selected by the user
-# and checked with opt-val and opt-bool. The format of options-spec follows.
+# and checked with 'opt-str' and 'opt-bool'. '$optionspec' contains a series
+# of options specifications separated by newlines, as follows:
#
# A boolean option is of the form:
#
## name[=0|1] => "Description of this boolean option"
#
-# The default is name=0, meaning that the option is disabled by default.
-# If name=1 is used to make the option enabled by default, the description should reflect
+# The default is 'name=0', meaning that the option is disabled by default.
+# If 'name=1' is used to make the option enabled by default, the description should reflect
# that with text like "Disable support for ...".
#
# An argument option (one which takes a parameter) is of the form:
#
## name:[=]value => "Description of this option"
#
-# If the name:value form is used, the value must be provided with the option (as --name=myvalue).
-# If the name:=value form is used, the value is optional and the given value is used as the default
+# If the 'name:value' form is used, the value must be provided with the option (as '--name=myvalue').
+# If the 'name:=value' form is used, the value is optional and the given value is used as the default
# if it is not provided.
#
-# Undocumented options are also supported by omitting the "=> description.
-# These options are not displayed with --help and can be useful for internal options or as aliases.
+# The description may contain '@default@', in which case it will be replaced with the default
+# value for the option (taking into account defaults specified with 'options-defaults'.
+#
+# Undocumented options are also supported by omitting the '=> description'.
+# These options are not displayed with '--help' and can be useful for internal options or as aliases.
#
-# For example, --disable-lfs is an alias for --disable=largefile:
+# For example, '--disable-lfs' is an alias for '--disable=largefile':
#
## lfs=1 largefile=1 => "Disable large file support"
#
@@ -430,7 +639,7 @@ proc options {optlist} {
# Check for invalid options
if {[opt-bool option-checking]} {
- foreach o [array names ::useropts] {
+ foreach o [dict keys $::autosetup(getopt)] {
if {$o ni $::autosetup(options)} {
user-error "Unknown option --$o"
}
@@ -438,22 +647,32 @@ proc options {optlist} {
}
}
+# @options-defaults dictionary
+#
+# Specifies a dictionary of options and a new default value for each of those options.
+# Use before any 'use' statements in 'auto.def' to change the defaults for
+# subsequently included modules.
+proc options-defaults {dict} {
+ foreach {n v} $dict {
+ dict set ::autosetup(options-defaults) $n $v
+ }
+}
+
proc config_guess {} {
- if {[file-isexec $::autosetup(dir)/config.guess]} {
- exec-with-stderr sh $::autosetup(dir)/config.guess
- if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} {
+ if {[file-isexec $::autosetup(dir)/autosetup-config.guess]} {
+ if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.guess} alias]} {
user-error $alias
}
return $alias
} else {
- configlog "No config.guess, so using uname"
+ configlog "No autosetup-config.guess, so using uname"
string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
}
}
proc config_sub {alias} {
- if {[file-isexec $::autosetup(dir)/config.sub]} {
- if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} {
+ if {[file-isexec $::autosetup(dir)/autosetup-config.sub]} {
+ if {[catch {exec-with-stderr sh $::autosetup(dir)/autosetup-config.sub $alias} alias]} {
user-error $alias
}
}
@@ -464,7 +683,7 @@ proc config_sub {alias} {
#
# Defines the named variable to the given value.
# These (name, value) pairs represent the results of the configuration check
-# and are available to be checked, modified and substituted.
+# and are available to be subsequently checked, modified and substituted.
#
proc define {name {value 1}} {
set ::define($name) $value
@@ -473,7 +692,7 @@ proc define {name {value 1}} {
# @undefine name
#
-# Undefine the named variable
+# Undefine the named variable.
#
proc undefine {name} {
unset -nocomplain ::define($name)
@@ -482,17 +701,26 @@ proc undefine {name} {
# @define-append name value ...
#
-# Appends the given value(s) to the given 'defined' variable.
-# If the variable is not defined or empty, it is set to $value.
+# Appends the given value(s) to the given "defined" variable.
+# If the variable is not defined or empty, it is set to '$value'.
# Otherwise the value is appended, separated by a space.
# Any extra values are similarly appended.
# If any value is already contained in the variable (as a substring) it is omitted.
#
proc define-append {name args} {
if {[get-define $name ""] ne ""} {
- # Make a token attempt to avoid duplicates
+ # Avoid duplicates
foreach arg $args {
- if {[string first $arg $::define($name)] == -1} {
+ if {$arg eq ""} {
+ continue
+ }
+ set found 0
+ foreach str [split $::define($name) " "] {
+ if {$str eq $arg} {
+ incr found
+ }
+ }
+ if {!$found} {
append ::define($name) " " $arg
}
}
@@ -504,7 +732,7 @@ proc define-append {name args} {
# @get-define name ?default=0?
#
-# Returns the current value of the 'defined' variable, or $default
+# Returns the current value of the "defined" variable, or '$default'
# if not set.
#
proc get-define {name {default 0}} {
@@ -524,9 +752,21 @@ proc is-defined {name} {
info exists ::define($name)
}
+# @is-define-set name
+#
+# Returns 1 if the given variable is defined and is set
+# to a value other than "" or 0
+#
+proc is-define-set {name} {
+ if {[get-define $name] in {0 ""}} {
+ return 0
+ }
+ return 1
+}
+
# @all-defines
#
-# Returns a dictionary (name value list) of all defined variables.
+# Returns a dictionary (name, value list) of all defined variables.
#
# This is suitable for use with 'dict', 'array set' or 'foreach'
# and allows for arbitrary processing of the defined variables.
@@ -538,9 +778,9 @@ proc all-defines {} {
# @get-env name default
#
-# If $name was specified on the command line, return it.
-# If $name was set in the environment, return it.
-# Otherwise return $default.
+# If '$name' was specified on the command line, return it.
+# Otherwise if '$name' was set in the environment, return it.
+# Otherwise return '$default'.
#
proc get-env {name default} {
if {[dict exists $::autosetup(cmdline) $name]} {
@@ -551,7 +791,7 @@ proc get-env {name default} {
# @env-is-set name
#
-# Returns 1 if the $name was specified on the command line or in the environment.
+# Returns 1 if '$name' was specified on the command line or in the environment.
# Note that an empty environment variable is not considered to be set.
#
proc env-is-set {name} {
@@ -567,7 +807,7 @@ proc env-is-set {name} {
# @readfile filename ?default=""?
#
# Return the contents of the file, without the trailing newline.
-# If the file doesn't exist or can't be read, returns $default.
+# If the file doesn't exist or can't be read, returns '$default'.
#
proc readfile {filename {default_value ""}} {
set result $default_value
@@ -581,7 +821,7 @@ proc readfile {filename {default_value ""}} {
# @writefile filename value
#
-# Creates the given file containing $value.
+# Creates the given file containing '$value'.
# Does not add an extra newline.
#
proc writefile {filename value} {
@@ -605,59 +845,56 @@ proc quote-argv {argv} {
join $args
}
-# @suffix suf list
+# @list-non-empty list
#
-# Takes a list and returns a new list with $suf appended
-# to each element
-#
-## suffix .c {a b c} => {a.c b.c c.c}
-#
-proc suffix {suf list} {
+# Returns a copy of the given list with empty elements removed
+proc list-non-empty {list} {
set result {}
foreach p $list {
- lappend result $p$suf
+ if {$p ne ""} {
+ lappend result $p
+ }
}
return $result
}
-# @prefix pre list
+# @find-executable-path name
#
-# Takes a list and returns a new list with $pre prepended
-# to each element
-#
-## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
+# Searches the path for an executable with the given name.
+# Note that the name may include some parameters, e.g. 'cc -mbig-endian',
+# in which case the parameters are ignored.
+# The full path to the executable if found, or "" if not found.
+# Returns 1 if found, or 0 if not.
#
-proc prefix {pre list} {
- set result {}
- foreach p $list {
- lappend result $pre$p
+proc find-executable-path {name} {
+ # Ignore any parameters
+ set name [lindex $name 0]
+ # The empty string is never a valid executable
+ if {$name ne ""} {
+ foreach p [split-path] {
+ dputs "Looking for $name in $p"
+ set exec [file join $p $name]
+ if {[file-isexec $exec]} {
+ dputs "Found $name -> $exec"
+ return $exec
+ }
+ }
}
- return $result
+ return {}
}
# @find-executable name
#
# Searches the path for an executable with the given name.
-# Note that the name may include some parameters, e.g. "cc -mbig-endian",
+# Note that the name may include some parameters, e.g. 'cc -mbig-endian',
# in which case the parameters are ignored.
# Returns 1 if found, or 0 if not.
#
proc find-executable {name} {
- # Ignore any parameters
- set name [lindex $name 0]
- if {$name eq ""} {
- # The empty string is never a valid executable
+ if {[find-executable-path $name] eq {}} {
return 0
}
- foreach p [split-path] {
- dputs "Looking for $name in $p"
- set exec [file join $p $name]
- if {[file-isexec $exec]} {
- dputs "Found $name -> $exec"
- return 1
- }
- }
- return 0
+ return 1
}
# @find-an-executable ?-required? name ...
@@ -692,7 +929,7 @@ proc find-an-executable {args} {
# @configlog msg
#
-# Writes the given message to the configuration log, config.log
+# Writes the given message to the configuration log, 'config.log'.
#
proc configlog {msg} {
if {![info exists ::autosetup(logfh)]} {
@@ -728,8 +965,8 @@ proc msg-result {msg} {
# @msg-quiet command ...
#
-# msg-quiet evaluates it's arguments as a command with output
-# from msg-checking and msg-result suppressed.
+# 'msg-quiet' evaluates it's arguments as a command with output
+# from 'msg-checking' and 'msg-result' suppressed.
#
# This is useful if a check needs to run a subcheck which isn't
# of interest to the user.
@@ -769,7 +1006,7 @@ proc dputs {msg} {
#
# Indicate incorrect usage to the user, including if required components
# or features are not found.
-# autosetup exits with a non-zero return code.
+# 'autosetup' exits with a non-zero return code.
#
proc user-error {msg} {
show-notices
@@ -816,6 +1053,17 @@ proc maybe-show-timestamp {} {
}
}
+# @autosetup-require-version required
+#
+# Checks the current version of 'autosetup' against '$required'.
+# A fatal error is generated if the current version is less than that required.
+#
+proc autosetup-require-version {required} {
+ if {[compare-versions $::autosetup(version) $required] < 0} {
+ user-error "autosetup version $required is required, but this is $::autosetup(version)"
+ }
+}
+
proc autosetup_version {} {
return "autosetup v$::autosetup(version)"
}
@@ -914,19 +1162,31 @@ proc autosetup_add_dep {filename} {
# when it is loaded.
#
proc use {args} {
+ global autosetup libmodule modsource
+
+ set dirs [list $autosetup(libdir)]
+ if {[info exists autosetup(srcdir)]} {
+ lappend dirs $autosetup(srcdir)/autosetup
+ }
foreach m $args {
- if {[info exists ::libmodule($m)]} {
+ if {[info exists libmodule($m)]} {
continue
}
- set ::libmodule($m) 1
- if {[info exists ::modsource($m)]} {
- automf_load eval $::modsource($m)
+ set libmodule($m) 1
+ if {[info exists modsource(${m}.tcl)]} {
+ automf_load eval $modsource(${m}.tcl)
} else {
- set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl]
+ set locs [list ${m}.tcl ${m}/init.tcl]
set found 0
- foreach source $sources {
- if {[file exists $source]} {
- incr found
+ foreach dir $dirs {
+ foreach loc $locs {
+ set source $dir/$loc
+ if {[file exists $source]} {
+ incr found
+ break
+ }
+ }
+ if {$found} {
break
}
}
@@ -943,6 +1203,18 @@ proc use {args} {
}
}
+proc autosetup_load_auto_modules {} {
+ global autosetup modsource
+ # First load any embedded auto modules
+ foreach mod [array names modsource *.auto] {
+ automf_load eval $modsource($mod)
+ }
+ # Now any external auto modules
+ foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
+ automf_load source $file
+ }
+}
+
# Load module source in the global scope by executing the given command
proc automf_load {args} {
if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
@@ -955,14 +1227,17 @@ set autosetup(exe) $::argv0
set autosetup(istcl) 1
set autosetup(start) [clock millis]
set autosetup(installed) 0
+set autosetup(sysinstall) 0
set autosetup(msg-checking) 0
set autosetup(msg-quiet) 0
+set autosetup(inittypes) {}
# Embedded modules are inserted below here
set autosetup(installed) 1
-# ----- module asciidoc-formatting -----
+set autosetup(sysinstall) 0
+# ----- @module asciidoc-formatting.tcl -----
-set modsource(asciidoc-formatting) {
+set modsource(asciidoc-formatting.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1030,15 +1305,15 @@ proc defn {first args} {
}
}
-# ----- module formatting -----
+# ----- @module formatting.tcl -----
-set modsource(formatting) {
+set modsource(formatting.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
# Module which provides common text formatting
-# This is designed for documenation which looks like:
+# This is designed for documentation which looks like:
# code {...}
# or
# code {
@@ -1087,21 +1362,28 @@ proc parse_code_block {text} {
}
}
-# ----- module getopt -----
+# ----- @module getopt.tcl -----
-set modsource(getopt) {
+set modsource(getopt.tcl) {
# Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/
# All rights reserved
# Simple getopt module
# Parse everything out of the argv list which looks like an option
-# Knows about --enable-thing and --disable-thing as alternatives for --thing=0 or --thing=1
# Everything which doesn't look like an option, or is after --, is left unchanged
+# Understands --enable-xxx as a synonym for --xxx to enable the boolean option xxx.
+# Understands --disable-xxx to disable the boolean option xxx.
+#
+# The returned value is a dictionary keyed by option name
+# Each value is a list of {type value} ... where type is "bool" or "str".
+# The value for a boolean option is 0 or 1. The value of a string option is the value given.
proc getopt {argvname} {
upvar $argvname argv
set nargv {}
+ set opts {}
+
for {set i 0} {$i < [llength $argv]} {incr i} {
set arg [lindex $argv $i]
@@ -1115,65 +1397,33 @@ proc getopt {argvname} {
}
if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} {
- lappend opts($name) $value
+ # --name=value
+ dict lappend opts $name [list str $value]
} elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} {
- if {$prefix eq "disable-"} {
- set value 0
- } else {
+ if {$prefix in {enable- ""}} {
set value 1
+ } else {
+ set value 0
}
- lappend opts($name) $value
+ dict lappend opts $name [list bool $value]
} else {
lappend nargv $arg
}
}
#puts "getopt: argv=[join $argv] => [join $nargv]"
- #parray opts
+ #array set getopt $opts
+ #parray getopt
set argv $nargv
- return [array get opts]
+ return $opts
}
-
-proc opt_val {optarrayname options {default {}}} {
- upvar $optarrayname opts
-
- set result {}
-
- foreach o $options {
- if {[info exists opts($o)]} {
- lappend result {*}$opts($o)
- }
- }
- if {[llength $result] == 0} {
- return $default
- }
- return $result
}
-proc opt_bool {optarrayname args} {
- upvar $optarrayname opts
-
- # Support the args being passed as a list
- if {[llength $args] == 1} {
- set args [lindex $args 0]
- }
+# ----- @module help.tcl -----
- foreach o $args {
- if {[info exists opts($o)]} {
- if {"1" in $opts($o) || "yes" in $opts($o)} {
- return 1
- }
- }
- }
- return 0
-}
-}
-
-# ----- module help -----
-
-set modsource(help) {
+set modsource(help.tcl) {
# Copyright (c) 2010 WorkWare Systems http://workware.net.au/
# All rights reserved
@@ -1205,6 +1455,24 @@ proc autosetup_help {what} {
exit 0
}
+proc autosetup_show_license {} {
+ global modsource autosetup
+ use_pager
+
+ if {[info exists modsource(LICENSE)]} {
+ puts $modsource(LICENSE)
+ return
+ }
+ foreach dir [list $autosetup(libdir) $autosetup(srcdir)] {
+ set path [file join $dir LICENSE]
+ if {[file exists $path]} {
+ puts [readfile $path]
+ return
+ }
+ }
+ puts "LICENSE not found"
+}
+
# If not already paged and stdout is a tty, pipe the output through the pager
# This is done by reinvoking autosetup with --nopager added
proc use_pager {} {
@@ -1257,6 +1525,12 @@ proc autosetup_reference {{type text}} {
proc autosetup_output_block {type lines} {
if {[llength $lines]} {
switch $type {
+ section {
+ section $lines
+ }
+ subsection {
+ subsection $lines
+ }
code {
codelines $lines
}
@@ -1278,16 +1552,30 @@ proc automf_command_reference {} {
lappend files $::autosetup(prog)
lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
- section "Core Commands"
- set type p
- set lines {}
- set cmd {}
+ # We want to process all non-module files before module files
+ # and then modules in alphabetical order.
+ # So examine all files and extract docs into doc($modulename) and doc(_core_)
+ #
+ # Each entry is a list of {type data} where $type is one of: section, subsection, code, list, p
+ # and $data is a string for section, subsection or a list of text lines for other types.
+
+ # XXX: Should commands be in alphabetical order too? Currently they are in file order.
+
+ set doc(_core_) {}
+ lappend doc(_core_) [list section "Core Commands"]
foreach file $files {
+ set modulename [file rootname [file tail $file]]
+ set current _core_
set f [open $file]
while {![eof $f]} {
set line [gets $f]
+ # Find embedded module names
+ if {[regexp {^#.*@module ([^ ]*)} $line -> modulename]} {
+ continue
+ }
+
# Find lines starting with "# @*" and continuing through the remaining comment lines
if {![regexp {^# @(.*)} $line -> cmd]} {
continue
@@ -1295,9 +1583,10 @@ proc automf_command_reference {} {
# Synopsis or command?
if {$cmd eq "synopsis:"} {
- section "Module: [file rootname [file tail $file]]"
+ set current $modulename
+ lappend doc($current) [list section "Module: $modulename"]
} else {
- subsection $cmd
+ lappend doc($current) [list subsection $cmd]
}
set lines {}
@@ -1322,7 +1611,7 @@ proc automf_command_reference {} {
if {$t ne $type || $cmd eq ""} {
# Finish the current block
- autosetup_output_block $type $lines
+ lappend doc($current) [list $type $lines]
set lines {}
set type $t
}
@@ -1331,16 +1620,25 @@ proc automf_command_reference {} {
}
}
- autosetup_output_block $type $lines
+ lappend doc($current) [list $type $lines]
}
close $f
}
+
+ # Now format and output the results
+
+ # _core_ will sort first
+ foreach module [lsort [array names doc]] {
+ foreach item $doc($module) {
+ autosetup_output_block {*}$item
+ }
+ }
}
}
-# ----- module init -----
+# ----- @module init.tcl -----
-set modsource(init) {
+set modsource(init.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1397,25 +1695,63 @@ proc autosetup_check_create {filename contents} {
}
}
-# ----- module install -----
+# ----- @module install.tcl -----
-set modsource(install) {
+set modsource(install.tcl) {
# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
# Module which can install autosetup
-proc autosetup_install {dir} {
- if {[catch {
+# autosetup(installed)=1 means that autosetup is not running from source
+# autosetup(sysinstall)=1 means that autosetup is running from a sysinstall version
+# shared=1 means that we are trying to do a sysinstall. This is only possible from the development source.
+
+proc autosetup_install {dir {shared 0}} {
+ global autosetup
+ if {$shared} {
+ if {$autosetup(installed) || $autosetup(sysinstall)} {
+ user-error "Can only --sysinstall from development sources"
+ }
+ } elseif {$autosetup(installed) && !$autosetup(sysinstall)} {
+ user-error "Can't --install from project install"
+ }
+
+ if {$autosetup(sysinstall)} {
+ # This is the sysinstall version, so install just uses references
cd $dir
+
+ puts "[autosetup_version] creating configure to use system-installed autosetup"
+ autosetup_create_configure 1
+ puts "Creating autosetup/README.autosetup"
file mkdir autosetup
+ autosetup_install_readme autosetup/README.autosetup 1
+ return
+ }
- set f [open autosetup/autosetup w]
+ if {[catch {
+ if {$shared} {
+ set target $dir/bin/autosetup
+ set installedas $target
+ } else {
+ if {$dir eq "."} {
+ set installedas autosetup
+ } else {
+ set installedas $dir/autosetup
+ }
+ cd $dir
+ file mkdir autosetup
+ set target autosetup/autosetup
+ }
+ set targetdir [file dirname $target]
+ file mkdir $targetdir
+
+ set f [open $target w]
- set publicmodules [glob $::autosetup(libdir)/*.auto]
+ set publicmodules {}
# First the main script, but only up until "CUT HERE"
- set in [open $::autosetup(dir)/autosetup]
+ set in [open $autosetup(dir)/autosetup]
while {[gets $in buf] >= 0} {
if {$buf ne "##-- CUT HERE --##"} {
puts $f $buf
@@ -1424,48 +1760,88 @@ proc autosetup_install {dir} {
# Insert the static modules here
# i.e. those which don't contain @synopsis:
+ # All modules are inserted if $shared is set
puts $f "set autosetup(installed) 1"
- foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] {
+ puts $f "set autosetup(sysinstall) $shared"
+ foreach file [lsort [glob $autosetup(libdir)/*.{tcl,auto}]] {
+ set modname [file tail $file]
+ set ext [file ext $modname]
set buf [readfile $file]
- if {[string match "*\n# @synopsis:*" $buf]} {
- lappend publicmodules $file
- continue
+ if {!$shared} {
+ if {$ext eq ".auto" || [string match "*\n# @synopsis:*" $buf]} {
+ lappend publicmodules $file
+ continue
+ }
}
- set modname [file rootname [file tail $file]]
- puts $f "# ----- module $modname -----"
+ dputs "install: importing lib/[file tail $file]"
+ puts $f "# ----- @module $modname -----"
puts $f "\nset modsource($modname) \{"
puts $f $buf
puts $f "\}\n"
}
+ if {$shared} {
+ foreach {srcname destname} [list $autosetup(libdir)/README.autosetup-lib README.autosetup \
+ $autosetup(srcdir)/LICENSE LICENSE] {
+ dputs "install: importing $srcname as $destname"
+ puts $f "\nset modsource($destname) \\\n[list [readfile $srcname]\n]\n"
+ }
+ }
}
close $in
close $f
- exec chmod 755 autosetup/autosetup
+ catch {exec chmod 755 $target}
+
+ set installfiles {autosetup-config.guess autosetup-config.sub autosetup-test-tclsh}
+ set removefiles {}
+
+ if {!$shared} {
+ autosetup_install_readme $targetdir/README.autosetup 0
- # Install public modules
- foreach file $publicmodules {
- autosetup_install_file $file autosetup
+ # Install public modules
+ foreach file $publicmodules {
+ set tail [file tail $file]
+ autosetup_install_file $file $targetdir/$tail
+ }
+ lappend installfiles jimsh0.c autosetup-find-tclsh LICENSE
+ lappend removefiles config.guess config.sub test-tclsh find-tclsh
+ } else {
+ lappend installfiles {sys-find-tclsh autosetup-find-tclsh}
}
# Install support files
- foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} {
- autosetup_install_file $::autosetup(dir)/$file autosetup
+ foreach fileinfo $installfiles {
+ if {[llength $fileinfo] == 2} {
+ lassign $fileinfo source dest
+ } else {
+ lassign $fileinfo source
+ set dest $source
+ }
+ autosetup_install_file $autosetup(dir)/$source $targetdir/$dest
}
- exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh
-
- writefile autosetup/README.autosetup \
- "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n"
+ # Remove obsolete files
+ foreach file $removefiles {
+ if {[file exists $targetdir/$file]} {
+ file delete $targetdir/$file
+ }
+ }
} error]} {
user-error "Failed to install autosetup: $error"
}
- puts "Installed [autosetup_version] to autosetup/"
+ if {$shared} {
+ set type "system"
+ } else {
+ set type "local"
+ }
+ puts "Installed $type [autosetup_version] to $installedas"
- # Now create 'configure' if necessary
- autosetup_create_configure
+ if {!$shared} {
+ # Now create 'configure' if necessary
+ autosetup_create_configure 0
+ }
}
-proc autosetup_create_configure {} {
+proc autosetup_create_configure {shared} {
if {[file exists configure]} {
if {!$::autosetup(force)} {
# Could this be an autosetup configure?
@@ -1480,36 +1856,71 @@ proc autosetup_create_configure {} {
} else {
puts "I don't see configure, so I will create it."
}
- writefile configure \
+ if {$shared} {
+ writefile configure \
+{#!/bin/sh
+WRAPPER="$0"; export WRAPPER; "autosetup" "$@"
+}
+ } else {
+ writefile configure \
{#!/bin/sh
dir="`dirname "$0"`/autosetup"
-WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
+WRAPPER="$0"; export WRAPPER; exec "`"$dir/autosetup-find-tclsh"`" "$dir/autosetup" "$@"
}
+ }
catch {exec chmod 755 configure}
}
# Append the contents of $file to filehandle $f
proc autosetup_install_append {f file} {
+ dputs "install: include $file"
set in [open $file]
puts $f [read $in]
close $in
}
-proc autosetup_install_file {file dir} {
- if {![file exists $file]} {
- error "Missing installation file '$file'"
+proc autosetup_install_file {source target} {
+ dputs "install: $source => $target"
+ if {![file exists $source]} {
+ error "Missing installation file '$source'"
}
- writefile [file join $dir [file tail $file]] [readfile $file]\n
+ writefile $target [readfile $source]\n
+ # If possible, copy the file mode
+ file stat $source stat
+ set mode [format %o [expr {$stat(mode) & 0x1ff}]]
+ catch {exec chmod $mode $target}
+}
+
+proc autosetup_install_readme {target sysinstall} {
+ set readme "README.autosetup created by [autosetup_version]\n\n"
+ if {$sysinstall} {
+ append readme \
+{This is the autosetup directory for a system install of autosetup.
+Loadable modules can be added here.
+}
+ } else {
+ append readme \
+{This is the autosetup directory for a local install of autosetup.
+It contains autosetup, support files and loadable modules.
}
+}
+
+ append readme {
+*.tcl files in this directory are optional modules which
+can be loaded with the 'use' directive.
+
+*.auto files in this directory are auto-loaded.
-if {$::autosetup(installed)} {
- user-error "autosetup can only be installed from development source, not from installed copy"
+For more information, see http://msteveb.github.com/autosetup/
+}
+ dputs "install: autosetup/README.autosetup"
+ writefile $target $readme
}
}
-# ----- module markdown-formatting -----
+# ----- @module markdown-formatting.tcl -----
-set modsource(markdown-formatting) {
+set modsource(markdown-formatting.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1580,9 +1991,9 @@ proc defn {first args} {
}
}
-# ----- module misc -----
+# ----- @module misc.tcl -----
-set modsource(misc) {
+set modsource(misc.tcl) {
# Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1758,9 +2169,9 @@ proc error-dump {msg opts fulltrace} {
}
}
-# ----- module text-formatting -----
+# ----- @module text-formatting.tcl -----
-set modsource(text-formatting) {
+set modsource(text-formatting.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1769,91 +2180,203 @@ set modsource(text-formatting) {
use formatting
proc wordwrap {text length {firstprefix ""} {nextprefix ""}} {
- set len 0
- set space $firstprefix
- foreach word [split $text] {
- set word [string trim $word]
- if {$word == ""} {
- continue
- }
- if {$len && [string length $space$word] + $len >= $length} {
- puts ""
- set len 0
- set space $nextprefix
- }
- incr len [string length $space$word]
-
- # Use man-page conventions for highlighting 'quoted' and *quoted*
- # single words.
- # Use x^Hx for *bold* and _^Hx for 'underline'.
- #
- # less and more will both understand this.
- # Pipe through 'col -b' to remove them.
- if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
- regsub -all . $bareword "_\b&" word
- append word $dot
- } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
- regsub -all . $bareword "&\b&" word
- append word $dot
- }
- puts -nonewline $space$word
- set space " "
- }
- if {$len} {
- puts ""
- }
+ set len 0
+ set space $firstprefix
+
+ foreach word [split $text] {
+ set word [string trim $word]
+ if {$word eq ""} {
+ continue
+ }
+ if {[info exists partial]} {
+ append partial " " $word
+ if {[string first $quote $word] < 0} {
+ # Haven't found end of quoted word
+ continue
+ }
+ # Finished quoted word
+ set word $partial
+ unset partial
+ unset quote
+ } else {
+ set quote [string index $word 0]
+ if {$quote in {' *}} {
+ if {[string first $quote $word 1] < 0} {
+ # Haven't found end of quoted word
+ # Not a whole word.
+ set first [string index $word 0]
+ # Start of quoted word
+ set partial $word
+ continue
+ }
+ }
+ }
+
+ if {$len && [string length $space$word] + $len >= $length} {
+ puts ""
+ set len 0
+ set space $nextprefix
+ }
+ incr len [string length $space$word]
+
+ # Use man-page conventions for highlighting 'quoted' and *quoted*
+ # single words.
+ # Use x^Hx for *bold* and _^Hx for 'underline'.
+ #
+ # less and more will both understand this.
+ # Pipe through 'col -b' to remove them.
+ if {[regexp {^'(.*)'(.*)} $word -> quoted after]} {
+ set quoted [string map {~ " "} $quoted]
+ regsub -all . $quoted "&\b&" quoted
+ set word $quoted$after
+ } elseif {[regexp {^[*](.*)[*](.*)} $word -> quoted after]} {
+ set quoted [string map {~ " "} $quoted]
+ regsub -all . $quoted "_\b&" quoted
+ set word $quoted$after
+ }
+ puts -nonewline $space$word
+ set space " "
+ }
+ if {[info exists partial]} {
+ # Missing end of quote
+ puts -nonewline $space$partial
+ }
+ if {$len} {
+ puts ""
+ }
}
proc title {text} {
- underline [string trim $text] =
- nl
+ underline [string trim $text] =
+ nl
}
proc p {text} {
- wordwrap $text 80
- nl
+ wordwrap $text 80
+ nl
}
proc codelines {lines} {
- foreach line $lines {
- puts " $line"
- }
- nl
+ foreach line $lines {
+ puts " $line"
+ }
+ nl
}
proc nl {} {
- puts ""
+ puts ""
}
proc underline {text char} {
- regexp "^(\[ \t\]*)(.*)" $text -> indent words
- puts $text
- puts $indent[string repeat $char [string length $words]]
+ regexp "^(\[ \t\]*)(.*)" $text -> indent words
+ puts $text
+ puts $indent[string repeat $char [string length $words]]
}
proc section {text} {
- underline "[string trim $text]" -
- nl
+ underline "[string trim $text]" -
+ nl
}
proc subsection {text} {
- underline "$text" ~
- nl
+ underline "$text" ~
+ nl
}
proc bullet {text} {
- wordwrap $text 76 " * " " "
+ wordwrap $text 76 " * " " "
}
proc indent {text} {
- wordwrap $text 76 " " " "
+ wordwrap $text 76 " " " "
}
proc defn {first args} {
- if {$first ne ""} {
- underline " $first" ~
- }
- foreach p $args {
- if {$p ne ""} {
- indent $p
- }
- }
+ if {$first ne ""} {
+ underline " $first" ~
+ }
+ foreach p $args {
+ if {$p ne ""} {
+ indent $p
+ }
+ }
+}
+}
+
+# ----- @module util.tcl -----
+
+set modsource(util.tcl) {
+# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# Module which contains miscellaneous utility functions
+
+# @compare-versions version1 version2
+#
+# Versions are of the form 'a.b.c' (may be any number of numeric components)
+#
+# Compares the two versions and returns:
+## -1 if v1 < v2
+## 0 if v1 == v2
+## 1 if v1 > v2
+#
+# If one version has fewer components than the other, 0 is substituted to the right. e.g.
+## 0.2 < 0.3
+## 0.2.5 > 0.2
+## 1.1 == 1.1.0
+#
+proc compare-versions {v1 v2} {
+ foreach c1 [split $v1 .] c2 [split $v2 .] {
+ if {$c1 eq ""} {
+ set c1 0
+ }
+ if {$c2 eq ""} {
+ set c2 0
+ }
+ if {$c1 < $c2} {
+ return -1
+ }
+ if {$c1 > $c2} {
+ return 1
+ }
+ }
+ return 0
+}
+
+# @suffix suf list
+#
+# Takes a list and returns a new list with '$suf' appended
+# to each element
+#
+## suffix .c {a b c} => {a.c b.c c.c}
+#
+proc suffix {suf list} {
+ set result {}
+ foreach p $list {
+ lappend result $p$suf
+ }
+ return $result
+}
+
+# @prefix pre list
+#
+# Takes a list and returns a new list with '$pre' prepended
+# to each element
+#
+## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
+#
+proc prefix {pre list} {
+ set result {}
+ foreach p $list {
+ lappend result $pre$p
+ }
+ return $result
+}
+
+# @lpop list
+#
+# Removes the last entry from the given list and returns it.
+proc lpop {listname} {
+ upvar $listname list
+ set val [lindex $list end]
+ set list [lrange $list 0 end-1]
+ return $val
}
}
-# ----- module wiki-formatting -----
+# ----- @module wiki-formatting.tcl -----
-set modsource(wiki-formatting) {
+set modsource(wiki-formatting.tcl) {
# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
# All rights reserved
@@ -1928,7 +2451,7 @@ if {$autosetup(debug)} {
}
if {[catch {main $argv} msg opts] == 1} {
show-notices
- autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
+ autosetup-full-error [error-dump $msg $opts $autosetup(debug)]
if {!$autosetup(debug)} {
puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
}