zlib: Don't use PASTE for INTMAX error messages
[jimtcl.git] / autosetup / autosetup
blob84886c277919a5d4d3450b8265c4d27b96635031
1 #!/bin/sh
2 # Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/
3 # All rights reserved
4 # vim:se syntax=tcl:
5 # \
6 dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@"
8 set autosetup(version) 0.6.5
10 # Can be set to 1 to debug early-init problems
11 set autosetup(debug) 0
13 ##################################################################
15 # Main flow of control, option handling
17 proc main {argv} {
18 global autosetup define
20 # There are 3 potential directories involved:
21 # 1. The directory containing autosetup (this script)
22 # 2. The directory containing auto.def
23 # 3. The current directory
25 # From this we need to determine:
26 # a. The path to this script (and related support files)
27 # b. The path to auto.def
28 # c. The build directory, where output files are created
30 # This is also complicated by the fact that autosetup may
31 # have been run via the configure wrapper ([getenv WRAPPER] is set)
33 # Here are the rules.
34 # a. This script is $::argv0
35 # => dir, prog, exe, libdir
36 # b. auto.def is in the directory containing the configure wrapper,
37 # otherwise it is in the current directory.
38 # => srcdir, autodef
39 # c. The build directory is the current directory
40 # => builddir, [pwd]
42 # 'misc' is needed before we can do anything, so set a temporary libdir
43 # in case this is the development version
44 set autosetup(libdir) [file dirname $::argv0]/lib
45 use misc
47 # (a)
48 set autosetup(dir) [realdir [file dirname [realpath $::argv0]]]
49 set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]]
50 set autosetup(exe) [getenv WRAPPER $autosetup(prog)]
51 if {$autosetup(installed)} {
52 set autosetup(libdir) $autosetup(dir)
53 } else {
54 set autosetup(libdir) [file join $autosetup(dir) lib]
56 autosetup_add_dep $autosetup(prog)
58 # (b)
59 if {[getenv WRAPPER ""] eq ""} {
60 # Invoked directly
61 set autosetup(srcdir) [pwd]
62 } else {
63 # Invoked via the configure wrapper
64 set autosetup(srcdir) [file dirname $autosetup(exe)]
66 set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def]
68 # (c)
69 set autosetup(builddir) [pwd]
71 set autosetup(argv) $argv
72 set autosetup(cmdline) {}
73 set autosetup(options) {}
74 set autosetup(optionhelp) {}
75 set autosetup(showhelp) 0
77 # Parse options
78 use getopt
80 array set ::useropts [getopt argv]
82 #"=Core Options:"
83 options-add {
84 help:=local => "display help and options. Optionally specify a module name, such as --help=system"
85 version => "display the version of autosetup"
86 ref:=text manual:=text
87 reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'"
88 debug => "display debugging output as autosetup runs"
89 install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)"
90 force init:=help => "create initial auto.def, etc. Use --init=help for known types"
91 # Undocumented options
92 option-checking=1
93 nopager
94 quiet
95 timing
96 conf:
99 #parray ::useropts
100 if {[opt-bool version]} {
101 puts $autosetup(version)
102 exit 0
105 # autosetup --conf=alternate-auto.def
106 if {[opt-val conf] ne ""} {
107 set autosetup(autodef) [opt-val conf]
110 # Debugging output (set this early)
111 incr autosetup(debug) [opt-bool debug]
112 incr autosetup(force) [opt-bool force]
113 incr autosetup(msg-quiet) [opt-bool quiet]
114 incr autosetup(msg-timing) [opt-bool timing]
116 # If the local module exists, source it now to allow for
117 # project-local customisations
118 if {[file exists $autosetup(libdir)/local.tcl]} {
119 use local
122 # Now any auto-load modules
123 foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] {
124 automf_load source $file
127 if {[opt-val help] ne ""} {
128 incr autosetup(showhelp)
129 use help
130 autosetup_help [opt-val help]
133 if {[opt-val {manual ref reference}] ne ""} {
134 use help
135 autosetup_reference [opt-val {manual ref reference}]
138 # Allow combining --install and --init
139 set earlyexit 0
140 if {[opt-val install] ne ""} {
141 use install
142 autosetup_install [opt-val install]
143 incr earlyexit
146 if {[opt-val init] ne ""} {
147 use init
148 autosetup_init [opt-val init]
149 incr earlyexit
152 if {$earlyexit} {
153 exit 0
156 if {![file exists $autosetup(autodef)]} {
157 # Check for invalid option first
158 options {}
159 user-error "No auto.def found in \"$autosetup(srcdir)\" (use [file tail $::autosetup(exe)] --init to create one)"
162 # Parse extra arguments into autosetup(cmdline)
163 foreach arg $argv {
164 if {[regexp {([^=]*)=(.*)} $arg -> n v]} {
165 dict set autosetup(cmdline) $n $v
166 define $n $v
167 } else {
168 user-error "Unexpected parameter: $arg"
172 autosetup_add_dep $autosetup(autodef)
174 define CONFIGURE_OPTS ""
175 foreach arg $autosetup(argv) {
176 define-append CONFIGURE_OPTS [quote-if-needed $arg]
178 define AUTOREMAKE [file-normalize $autosetup(exe)]
179 define-append AUTOREMAKE [get-define CONFIGURE_OPTS]
182 # Log how we were invoked
183 configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
185 # Note that auto.def is *not* loaded in the global scope
186 source $autosetup(autodef)
188 # Could warn here if options {} was not specified
190 show-notices
192 if {$autosetup(debug)} {
193 msg-result "Writing all defines to config.log"
194 configlog "================ defines ======================"
195 foreach n [lsort [array names define]] {
196 configlog "define $n $define($n)"
200 exit 0
203 # @opt-bool option ...
205 # Check each of the named, boolean options and return 1 if any of them have
206 # been set by the user.
208 proc opt-bool {args} {
209 option-check-names {*}$args
210 opt_bool ::useropts {*}$args
213 # @opt-val option-list ?default=""?
215 # Returns a list containing all the values given for the non-boolean options in 'option-list'.
216 # There will be one entry in the list for each option given by the user, including if the
217 # same option was used multiple times.
218 # If only a single value is required, use something like:
220 ## lindex [opt-val $names] end
222 # If no options were set, $default is returned (exactly, not as a list).
224 proc opt-val {names {default ""}} {
225 option-check-names {*}$names
226 join [opt_val ::useropts $names $default]
229 proc option-check-names {args} {
230 foreach o $args {
231 if {$o ni $::autosetup(options)} {
232 autosetup-error "Request for undeclared option --$o"
237 # Parse the option definition in $opts and update
238 # ::useropts() and ::autosetup(optionhelp) appropriately
240 proc options-add {opts {header ""}} {
241 global useropts autosetup
243 # First weed out comment lines
244 set realopts {}
245 foreach line [split $opts \n] {
246 if {![string match "#*" [string trimleft $line]]} {
247 append realopts $line \n
250 set opts $realopts
252 for {set i 0} {$i < [llength $opts]} {incr i} {
253 set opt [lindex $opts $i]
254 if {[string match =* $opt]} {
255 # This is a special heading
256 lappend autosetup(optionhelp) $opt ""
257 set header {}
258 continue
261 #puts "i=$i, opt=$opt"
262 regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value
263 if {$name in $autosetup(options)} {
264 autosetup-error "Option $name already specified"
267 #puts "$opt => $name $colon $equal $value"
269 # Find the corresponding value in the user options
270 # and set the default if necessary
271 if {[string match "-*" $opt]} {
272 # This is a documentation-only option, like "-C <dir>"
273 set opthelp $opt
274 } elseif {$colon eq ""} {
275 # Boolean option
276 lappend autosetup(options) $name
278 if {![info exists useropts($name)]} {
279 set useropts($name) $value
281 if {$value eq "1"} {
282 set opthelp "--disable-$name"
283 } else {
284 set opthelp "--$name"
286 } else {
287 # String option.
288 lappend autosetup(options) $name
290 if {$equal eq "="} {
291 if {[info exists useropts($name)]} {
292 # If the user specified the option with no value, the value will be "1"
293 # Replace with the default
294 if {$useropts($name) eq "1"} {
295 set useropts($name) $value
298 set opthelp "--$name?=$value?"
299 } else {
300 set opthelp "--$name=$value"
304 # Now create the help for this option if appropriate
305 if {[lindex $opts $i+1] eq "=>"} {
306 set desc [lindex $opts $i+2]
307 #string match \n* $desc
308 if {$header ne ""} {
309 lappend autosetup(optionhelp) $header ""
310 set header ""
312 # A multi-line description
313 lappend autosetup(optionhelp) $opthelp $desc
314 incr i 2
319 # @module-options optionlist
321 # Like 'options', but used within a module.
322 proc module-options {opts} {
323 set header ""
324 if {$::autosetup(showhelp) > 1 && [llength $opts]} {
325 set header "Module Options:"
327 options-add $opts $header
329 if {$::autosetup(showhelp)} {
330 # Ensure that the module isn't executed on --help
331 # We are running under eval or source, so use break
332 # to prevent further execution
333 #return -code break -level 2
334 return -code break
338 proc max {a b} {
339 expr {$a > $b ? $a : $b}
342 proc options-wrap-desc {text length firstprefix nextprefix initial} {
343 set len $initial
344 set space $firstprefix
345 foreach word [split $text] {
346 set word [string trim $word]
347 if {$word == ""} {
348 continue
350 if {$len && [string length $space$word] + $len >= $length} {
351 puts ""
352 set len 0
353 set space $nextprefix
355 incr len [string length $space$word]
356 puts -nonewline $space$word
357 set space " "
359 if {$len} {
360 puts ""
364 proc options-show {} {
365 # Determine the max option width
366 set max 0
367 foreach {opt desc} $::autosetup(optionhelp) {
368 if {[string match =* $opt] || [string match \n* $desc]} {
369 continue
371 set max [max $max [string length $opt]]
373 set indent [string repeat " " [expr $max+4]]
374 set cols [getenv COLUMNS 80]
375 catch {
376 lassign [exec stty size] rows cols
378 incr cols -1
379 # Now output
380 foreach {opt desc} $::autosetup(optionhelp) {
381 if {[string match =* $opt]} {
382 puts [string range $opt 1 end]
383 continue
385 puts -nonewline " [format %-${max}s $opt]"
386 if {[string match \n* $desc]} {
387 puts $desc
388 } else {
389 options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2]
394 # @options options-spec
396 # Specifies configuration-time options which may be selected by the user
397 # and checked with opt-val and opt-bool. The format of options-spec follows.
399 # A boolean option is of the form:
401 ## name[=0|1] => "Description of this boolean option"
403 # The default is name=0, meaning that the option is disabled by default.
404 # If name=1 is used to make the option enabled by default, the description should reflect
405 # that with text like "Disable support for ...".
407 # An argument option (one which takes a parameter) is of the form:
409 ## name:[=]value => "Description of this option"
411 # If the name:value form is used, the value must be provided with the option (as --name=myvalue).
412 # If the name:=value form is used, the value is optional and the given value is used as the default
413 # if it is not provided.
415 # Undocumented options are also supported by omitting the "=> description.
416 # These options are not displayed with --help and can be useful for internal options or as aliases.
418 # For example, --disable-lfs is an alias for --disable=largefile:
420 ## lfs=1 largefile=1 => "Disable large file support"
422 proc options {optlist} {
423 # Allow options as a list or args
424 options-add $optlist "Local Options:"
426 if {$::autosetup(showhelp)} {
427 options-show
428 exit 0
431 # Check for invalid options
432 if {[opt-bool option-checking]} {
433 foreach o [array names ::useropts] {
434 if {$o ni $::autosetup(options)} {
435 user-error "Unknown option --$o"
441 proc config_guess {} {
442 if {[file-isexec $::autosetup(dir)/config.guess]} {
443 exec-with-stderr sh $::autosetup(dir)/config.guess
444 if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} {
445 user-error $alias
447 return $alias
448 } else {
449 configlog "No config.guess, so using uname"
450 string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r]
454 proc config_sub {alias} {
455 if {[file-isexec $::autosetup(dir)/config.sub]} {
456 if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} {
457 user-error $alias
460 return $alias
463 # @define name ?value=1?
465 # Defines the named variable to the given value.
466 # These (name, value) pairs represent the results of the configuration check
467 # and are available to be checked, modified and substituted.
469 proc define {name {value 1}} {
470 set ::define($name) $value
471 #dputs "$name <= $value"
474 # @undefine name
476 # Undefine the named variable
478 proc undefine {name} {
479 unset -nocomplain ::define($name)
480 #dputs "$name <= <undef>"
483 # @define-append name value ...
485 # Appends the given value(s) to the given 'defined' variable.
486 # If the variable is not defined or empty, it is set to $value.
487 # Otherwise the value is appended, separated by a space.
488 # Any extra values are similarly appended.
489 # If any value is already contained in the variable (as a substring) it is omitted.
491 proc define-append {name args} {
492 if {[get-define $name ""] ne ""} {
493 # Make a token attempt to avoid duplicates
494 foreach arg $args {
495 if {[string first $arg $::define($name)] == -1} {
496 append ::define($name) " " $arg
499 } else {
500 set ::define($name) [join $args]
502 #dputs "$name += [join $args] => $::define($name)"
505 # @get-define name ?default=0?
507 # Returns the current value of the 'defined' variable, or $default
508 # if not set.
510 proc get-define {name {default 0}} {
511 if {[info exists ::define($name)]} {
512 #dputs "$name => $::define($name)"
513 return $::define($name)
515 #dputs "$name => $default"
516 return $default
519 # @is-defined name
521 # Returns 1 if the given variable is defined.
523 proc is-defined {name} {
524 info exists ::define($name)
527 # @all-defines
529 # Returns a dictionary (name value list) of all defined variables.
531 # This is suitable for use with 'dict', 'array set' or 'foreach'
532 # and allows for arbitrary processing of the defined variables.
534 proc all-defines {} {
535 array get ::define
539 # @get-env name default
541 # If $name was specified on the command line, return it.
542 # If $name was set in the environment, return it.
543 # Otherwise return $default.
545 proc get-env {name default} {
546 if {[dict exists $::autosetup(cmdline) $name]} {
547 return [dict get $::autosetup(cmdline) $name]
549 getenv $name $default
552 # @env-is-set name
554 # Returns 1 if the $name was specified on the command line or in the environment.
555 # Note that an empty environment variable is not considered to be set.
557 proc env-is-set {name} {
558 if {[dict exists $::autosetup(cmdline) $name]} {
559 return 1
561 if {[getenv $name ""] ne ""} {
562 return 1
564 return 0
567 # @readfile filename ?default=""?
569 # Return the contents of the file, without the trailing newline.
570 # If the file doesn't exist or can't be read, returns $default.
572 proc readfile {filename {default_value ""}} {
573 set result $default_value
574 catch {
575 set f [open $filename]
576 set result [read -nonewline $f]
577 close $f
579 return $result
582 # @writefile filename value
584 # Creates the given file containing $value.
585 # Does not add an extra newline.
587 proc writefile {filename value} {
588 set f [open $filename w]
589 puts -nonewline $f $value
590 close $f
593 proc quote-if-needed {str} {
594 if {[string match {*[\" ]*} $str]} {
595 return \"[string map [list \" \\" \\ \\\\] $str]\"
597 return $str
600 proc quote-argv {argv} {
601 set args {}
602 foreach arg $argv {
603 lappend args [quote-if-needed $arg]
605 join $args
608 # @suffix suf list
610 # Takes a list and returns a new list with $suf appended
611 # to each element
613 ## suffix .c {a b c} => {a.c b.c c.c}
615 proc suffix {suf list} {
616 set result {}
617 foreach p $list {
618 lappend result $p$suf
620 return $result
623 # @prefix pre list
625 # Takes a list and returns a new list with $pre prepended
626 # to each element
628 ## prefix jim- {a.c b.c} => {jim-a.c jim-b.c}
630 proc prefix {pre list} {
631 set result {}
632 foreach p $list {
633 lappend result $pre$p
635 return $result
638 # @find-executable name
640 # Searches the path for an executable with the given name.
641 # Note that the name may include some parameters, e.g. "cc -mbig-endian",
642 # in which case the parameters are ignored.
643 # Returns 1 if found, or 0 if not.
645 proc find-executable {name} {
646 # Ignore any parameters
647 set name [lindex $name 0]
648 if {$name eq ""} {
649 # The empty string is never a valid executable
650 return 0
652 foreach p [split-path] {
653 dputs "Looking for $name in $p"
654 set exec [file join $p $name]
655 if {[file-isexec $exec]} {
656 dputs "Found $name -> $exec"
657 return 1
660 return 0
663 # @find-an-executable ?-required? name ...
665 # Given a list of possible executable names,
666 # searches for one of these on the path.
668 # Returns the name found, or "" if none found.
669 # If the first parameter is '-required', an error is generated
670 # if no executable is found.
672 proc find-an-executable {args} {
673 set required 0
674 if {[lindex $args 0] eq "-required"} {
675 set args [lrange $args 1 end]
676 incr required
678 foreach name $args {
679 if {[find-executable $name]} {
680 return $name
683 if {$required} {
684 if {[llength $args] == 1} {
685 user-error "failed to find: [join $args]"
686 } else {
687 user-error "failed to find one of: [join $args]"
690 return ""
693 # @configlog msg
695 # Writes the given message to the configuration log, config.log
697 proc configlog {msg} {
698 if {![info exists ::autosetup(logfh)]} {
699 set ::autosetup(logfh) [open config.log w]
701 puts $::autosetup(logfh) $msg
704 # @msg-checking msg
706 # Writes the message with no newline to stdout.
708 proc msg-checking {msg} {
709 if {$::autosetup(msg-quiet) == 0} {
710 maybe-show-timestamp
711 puts -nonewline $msg
712 set ::autosetup(msg-checking) 1
716 # @msg-result msg
718 # Writes the message to stdout.
720 proc msg-result {msg} {
721 if {$::autosetup(msg-quiet) == 0} {
722 maybe-show-timestamp
723 puts $msg
724 set ::autosetup(msg-checking) 0
725 show-notices
729 # @msg-quiet command ...
731 # msg-quiet evaluates it's arguments as a command with output
732 # from msg-checking and msg-result suppressed.
734 # This is useful if a check needs to run a subcheck which isn't
735 # of interest to the user.
736 proc msg-quiet {args} {
737 incr ::autosetup(msg-quiet)
738 set rc [uplevel 1 $args]
739 incr ::autosetup(msg-quiet) -1
740 return $rc
743 # Will be overridden by 'use misc'
744 proc error-stacktrace {msg} {
745 return $msg
748 proc error-location {msg} {
749 return $msg
752 ##################################################################
754 # Debugging output
756 proc dputs {msg} {
757 if {$::autosetup(debug)} {
758 puts $msg
762 ##################################################################
764 # User and system warnings and errors
766 # Usage errors such as wrong command line options
768 # @user-error msg
770 # Indicate incorrect usage to the user, including if required components
771 # or features are not found.
772 # autosetup exits with a non-zero return code.
774 proc user-error {msg} {
775 show-notices
776 puts stderr "Error: $msg"
777 puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options"
778 exit 1
781 # @user-notice msg
783 # Output the given message to stderr.
785 proc user-notice {msg} {
786 lappend ::autosetup(notices) $msg
789 # Incorrect usage in the auto.def file. Identify the location.
790 proc autosetup-error {msg} {
791 autosetup-full-error [error-location $msg]
794 # Like autosetup-error, except $msg is the full error message.
795 proc autosetup-full-error {msg} {
796 show-notices
797 puts stderr $msg
798 exit 1
801 proc show-notices {} {
802 if {$::autosetup(msg-checking)} {
803 puts ""
804 set ::autosetup(msg-checking) 0
806 flush stdout
807 if {[info exists ::autosetup(notices)]} {
808 puts stderr [join $::autosetup(notices) \n]
809 unset ::autosetup(notices)
813 proc maybe-show-timestamp {} {
814 if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} {
815 puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]]
819 proc autosetup_version {} {
820 return "autosetup v$::autosetup(version)"
823 ##################################################################
825 # Directory/path handling
828 proc realdir {dir} {
829 set oldpwd [pwd]
830 cd $dir
831 set pwd [pwd]
832 cd $oldpwd
833 return $pwd
836 # Follow symlinks until we get to something which is not a symlink
837 proc realpath {path} {
838 while {1} {
839 if {[catch {
840 set path [file readlink $path]
841 }]} {
842 # Not a link
843 break
846 return $path
849 # Convert absolute path, $path into a path relative
850 # to the given directory (or the current dir, if not given).
852 proc relative-path {path {pwd {}}} {
853 set diff 0
854 set same 0
855 set newf {}
856 set prefix {}
857 set path [file-normalize $path]
858 if {$pwd eq ""} {
859 set pwd [pwd]
860 } else {
861 set pwd [file-normalize $pwd]
864 if {$path eq $pwd} {
865 return .
868 # Try to make the filename relative to the current dir
869 foreach p [split $pwd /] f [split $path /] {
870 if {$p ne $f} {
871 incr diff
872 } elseif {!$diff} {
873 incr same
875 if {$diff} {
876 if {$p ne ""} {
877 # Add .. for sibling or parent dir
878 lappend prefix ..
880 if {$f ne ""} {
881 lappend newf $f
885 if {$same == 1 || [llength $prefix] > 3} {
886 return $path
889 file join [join $prefix /] [join $newf /]
892 # Add filename as a dependency to rerun autosetup
893 # The name will be normalised (converted to a full path)
895 proc autosetup_add_dep {filename} {
896 lappend ::autosetup(deps) [file-normalize $filename]
899 ##################################################################
901 # Library module support
904 # @use module ...
906 # Load the given library modules.
907 # e.g. 'use cc cc-shared'
909 # Note that module 'X' is implemented in either 'autosetup/X.tcl'
910 # or 'autosetup/X/init.tcl'
912 # The latter form is useful for a complex module which requires additional
913 # support file. In this form, '$::usedir' is set to the module directory
914 # when it is loaded.
916 proc use {args} {
917 foreach m $args {
918 if {[info exists ::libmodule($m)]} {
919 continue
921 set ::libmodule($m) 1
922 if {[info exists ::modsource($m)]} {
923 automf_load eval $::modsource($m)
924 } else {
925 set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl]
926 set found 0
927 foreach source $sources {
928 if {[file exists $source]} {
929 incr found
930 break
933 if {$found} {
934 # For the convenience of the "use" source, point to the directory
935 # it is being loaded from
936 set ::usedir [file dirname $source]
937 automf_load source $source
938 autosetup_add_dep $source
939 } else {
940 autosetup-error "use: No such module: $m"
946 # Load module source in the global scope by executing the given command
947 proc automf_load {args} {
948 if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} {
949 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
953 # Initial settings
954 set autosetup(exe) $::argv0
955 set autosetup(istcl) 1
956 set autosetup(start) [clock millis]
957 set autosetup(installed) 0
958 set autosetup(msg-checking) 0
959 set autosetup(msg-quiet) 0
961 # Embedded modules are inserted below here
962 set autosetup(installed) 1
963 # ----- module asciidoc-formatting -----
965 set modsource(asciidoc-formatting) {
966 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
967 # All rights reserved
969 # Module which provides text formatting
970 # asciidoc format
972 use formatting
974 proc para {text} {
975 regsub -all "\[ \t\n\]+" [string trim $text] " "
977 proc title {text} {
978 underline [para $text] =
981 proc p {text} {
982 puts [para $text]
985 proc code {text} {
986 foreach line [parse_code_block $text] {
987 puts " $line"
991 proc codelines {lines} {
992 foreach line $lines {
993 puts " $line"
997 proc nl {} {
998 puts ""
1000 proc underline {text char} {
1001 regexp "^(\[ \t\]*)(.*)" $text -> indent words
1002 puts $text
1003 puts $indent[string repeat $char [string length $words]]
1005 proc section {text} {
1006 underline "[para $text]" -
1009 proc subsection {text} {
1010 underline "$text" ~
1013 proc bullet {text} {
1014 puts "* [para $text]"
1016 proc indent {text} {
1017 puts " :: "
1018 puts [para $text]
1020 proc defn {first args} {
1021 set sep ""
1022 if {$first ne ""} {
1023 puts "${first}::"
1024 } else {
1025 puts " :: "
1027 set defn [string trim [join $args \n]]
1028 regsub -all "\n\n" $defn "\n ::\n" defn
1029 puts $defn
1033 # ----- module formatting -----
1035 set modsource(formatting) {
1036 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1037 # All rights reserved
1039 # Module which provides common text formatting
1041 # This is designed for documenation which looks like:
1042 # code {...}
1043 # or
1044 # code {
1045 # ...
1046 # ...
1048 # In the second case, we need to work out the indenting
1049 # and strip it from all lines but preserve the remaining indenting.
1050 # Note that all lines need to be indented with the same initial
1051 # spaces/tabs.
1053 # Returns a list of lines with the indenting removed.
1055 proc parse_code_block {text} {
1056 # If the text begins with newline, take the following text,
1057 # otherwise just return the original
1058 if {![regexp "^\n(.*)" $text -> text]} {
1059 return [list [string trim $text]]
1062 # And trip spaces off the end
1063 set text [string trimright $text]
1065 set min 100
1066 # Examine each line to determine the minimum indent
1067 foreach line [split $text \n] {
1068 if {$line eq ""} {
1069 # Ignore empty lines for the indent calculation
1070 continue
1072 regexp "^(\[ \t\]*)" $line -> indent
1073 set len [string length $indent]
1074 if {$len < $min} {
1075 set min $len
1079 # Now make a list of lines with this indent removed
1080 set lines {}
1081 foreach line [split $text \n] {
1082 lappend lines [string range $line $min end]
1085 # Return the result
1086 return $lines
1090 # ----- module getopt -----
1092 set modsource(getopt) {
1093 # Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/
1094 # All rights reserved
1096 # Simple getopt module
1098 # Parse everything out of the argv list which looks like an option
1099 # Knows about --enable-thing and --disable-thing as alternatives for --thing=0 or --thing=1
1100 # Everything which doesn't look like an option, or is after --, is left unchanged
1101 proc getopt {argvname} {
1102 upvar $argvname argv
1103 set nargv {}
1105 for {set i 0} {$i < [llength $argv]} {incr i} {
1106 set arg [lindex $argv $i]
1108 #dputs arg=$arg
1110 if {$arg eq "--"} {
1111 # End of options
1112 incr i
1113 lappend nargv {*}[lrange $argv $i end]
1114 break
1117 if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} {
1118 lappend opts($name) $value
1119 } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} {
1120 if {$prefix eq "disable-"} {
1121 set value 0
1122 } else {
1123 set value 1
1125 lappend opts($name) $value
1126 } else {
1127 lappend nargv $arg
1131 #puts "getopt: argv=[join $argv] => [join $nargv]"
1132 #parray opts
1134 set argv $nargv
1136 return [array get opts]
1139 proc opt_val {optarrayname options {default {}}} {
1140 upvar $optarrayname opts
1142 set result {}
1144 foreach o $options {
1145 if {[info exists opts($o)]} {
1146 lappend result {*}$opts($o)
1149 if {[llength $result] == 0} {
1150 return $default
1152 return $result
1155 proc opt_bool {optarrayname args} {
1156 upvar $optarrayname opts
1158 # Support the args being passed as a list
1159 if {[llength $args] == 1} {
1160 set args [lindex $args 0]
1163 foreach o $args {
1164 if {[info exists opts($o)]} {
1165 if {"1" in $opts($o) || "yes" in $opts($o)} {
1166 return 1
1170 return 0
1174 # ----- module help -----
1176 set modsource(help) {
1177 # Copyright (c) 2010 WorkWare Systems http://workware.net.au/
1178 # All rights reserved
1180 # Module which provides usage, help and the command reference
1182 proc autosetup_help {what} {
1183 use_pager
1185 puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n"
1186 puts "This is [autosetup_version], a build environment \"autoconfigurator\""
1187 puts "See the documentation online at http://msteveb.github.com/autosetup/\n"
1189 if {$what eq "local"} {
1190 if {[file exists $::autosetup(autodef)]} {
1191 # This relies on auto.def having a call to 'options'
1192 # which will display options and quit
1193 source $::autosetup(autodef)
1194 } else {
1195 options-show
1197 } else {
1198 incr ::autosetup(showhelp)
1199 if {[catch {use $what}]} {
1200 user-error "Unknown module: $what"
1201 } else {
1202 options-show
1205 exit 0
1208 # If not already paged and stdout is a tty, pipe the output through the pager
1209 # This is done by reinvoking autosetup with --nopager added
1210 proc use_pager {} {
1211 if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} {
1212 if {[catch {
1213 exec [info nameofexecutable] $::argv0 --nopager {*}$::argv |& {*}[getenv PAGER] >@stdout <@stdin 2>@stderr
1214 } msg opts] == 1} {
1215 if {[dict get $opts -errorcode] eq "NONE"} {
1216 # an internal/exec error
1217 puts stderr $msg
1218 exit 1
1221 exit 0
1225 # Outputs the autosetup references in one of several formats
1226 proc autosetup_reference {{type text}} {
1228 use_pager
1230 switch -glob -- $type {
1231 wiki {use wiki-formatting}
1232 ascii* {use asciidoc-formatting}
1233 md - markdown {use markdown-formatting}
1234 default {use text-formatting}
1237 title "[autosetup_version] -- Command Reference"
1239 section {Introduction}
1242 See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup'
1246 'autosetup' provides a number of built-in commands which
1247 are documented below. These may be used from 'auto.def' to test
1248 for features, define variables, create files from templates and
1249 other similar actions.
1252 automf_command_reference
1254 exit 0
1257 proc autosetup_output_block {type lines} {
1258 if {[llength $lines]} {
1259 switch $type {
1260 code {
1261 codelines $lines
1264 p [join $lines]
1266 list {
1267 foreach line $lines {
1268 bullet $line
1276 # Generate a command reference from inline documentation
1277 proc automf_command_reference {} {
1278 lappend files $::autosetup(prog)
1279 lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]]
1281 section "Core Commands"
1282 set type p
1283 set lines {}
1284 set cmd {}
1286 foreach file $files {
1287 set f [open $file]
1288 while {![eof $f]} {
1289 set line [gets $f]
1291 # Find lines starting with "# @*" and continuing through the remaining comment lines
1292 if {![regexp {^# @(.*)} $line -> cmd]} {
1293 continue
1296 # Synopsis or command?
1297 if {$cmd eq "synopsis:"} {
1298 section "Module: [file rootname [file tail $file]]"
1299 } else {
1300 subsection $cmd
1303 set lines {}
1304 set type p
1306 # Now the description
1307 while {![eof $f]} {
1308 set line [gets $f]
1310 if {![regexp {^#(#)? ?(.*)} $line -> hash cmd]} {
1311 break
1313 if {$hash eq "#"} {
1314 set t code
1315 } elseif {[regexp {^- (.*)} $cmd -> cmd]} {
1316 set t list
1317 } else {
1318 set t p
1321 #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd"
1323 if {$t ne $type || $cmd eq ""} {
1324 # Finish the current block
1325 autosetup_output_block $type $lines
1326 set lines {}
1327 set type $t
1329 if {$cmd ne ""} {
1330 lappend lines $cmd
1334 autosetup_output_block $type $lines
1336 close $f
1341 # ----- module init -----
1343 set modsource(init) {
1344 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1345 # All rights reserved
1347 # Module to help create auto.def and configure
1349 proc autosetup_init {type} {
1350 set help 0
1351 if {$type in {? help}} {
1352 incr help
1353 } elseif {![dict exists $::autosetup(inittypes) $type]} {
1354 puts "Unknown type, --init=$type"
1355 incr help
1357 if {$help} {
1358 puts "Use one of the following types (e.g. --init=make)\n"
1359 foreach type [lsort [dict keys $::autosetup(inittypes)]] {
1360 lassign [dict get $::autosetup(inittypes) $type] desc
1361 # XXX: Use the options-show code to wrap the description
1362 puts [format "%-10s %s" $type $desc]
1364 return
1366 lassign [dict get $::autosetup(inittypes) $type] desc script
1368 puts "Initialising $type: $desc\n"
1370 # All initialisations happens in the top level srcdir
1371 cd $::autosetup(srcdir)
1373 uplevel #0 $script
1376 proc autosetup_add_init_type {type desc script} {
1377 dict set ::autosetup(inittypes) $type [list $desc $script]
1380 # This is for in creating build-system init scripts
1382 # If the file doesn't exist, create it containing $contents
1383 # If the file does exist, only overwrite if --force is specified.
1385 proc autosetup_check_create {filename contents} {
1386 if {[file exists $filename]} {
1387 if {!$::autosetup(force)} {
1388 puts "I see $filename already exists."
1389 return
1390 } else {
1391 puts "I will overwrite the existing $filename because you used --force."
1393 } else {
1394 puts "I don't see $filename, so I will create it."
1396 writefile $filename $contents
1400 # ----- module install -----
1402 set modsource(install) {
1403 # Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/
1404 # All rights reserved
1406 # Module which can install autosetup
1408 proc autosetup_install {dir} {
1409 if {[catch {
1410 cd $dir
1411 file mkdir autosetup
1413 set f [open autosetup/autosetup w]
1415 set publicmodules [glob $::autosetup(libdir)/*.auto]
1417 # First the main script, but only up until "CUT HERE"
1418 set in [open $::autosetup(dir)/autosetup]
1419 while {[gets $in buf] >= 0} {
1420 if {$buf ne "##-- CUT HERE --##"} {
1421 puts $f $buf
1422 continue
1425 # Insert the static modules here
1426 # i.e. those which don't contain @synopsis:
1427 puts $f "set autosetup(installed) 1"
1428 foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] {
1429 set buf [readfile $file]
1430 if {[string match "*\n# @synopsis:*" $buf]} {
1431 lappend publicmodules $file
1432 continue
1434 set modname [file rootname [file tail $file]]
1435 puts $f "# ----- module $modname -----"
1436 puts $f "\nset modsource($modname) \{"
1437 puts $f $buf
1438 puts $f "\}\n"
1441 close $in
1442 close $f
1443 exec chmod 755 autosetup/autosetup
1445 # Install public modules
1446 foreach file $publicmodules {
1447 autosetup_install_file $file autosetup
1450 # Install support files
1451 foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} {
1452 autosetup_install_file $::autosetup(dir)/$file autosetup
1454 exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh
1456 writefile autosetup/README.autosetup \
1457 "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n"
1459 } error]} {
1460 user-error "Failed to install autosetup: $error"
1462 puts "Installed [autosetup_version] to autosetup/"
1464 # Now create 'configure' if necessary
1465 autosetup_create_configure
1468 proc autosetup_create_configure {} {
1469 if {[file exists configure]} {
1470 if {!$::autosetup(force)} {
1471 # Could this be an autosetup configure?
1472 if {![string match "*\nWRAPPER=*" [readfile configure]]} {
1473 puts "I see configure, but not created by autosetup, so I won't overwrite it."
1474 puts "Remove it or use --force to overwrite."
1475 return
1477 } else {
1478 puts "I will overwrite the existing configure because you used --force."
1480 } else {
1481 puts "I don't see configure, so I will create it."
1483 writefile configure \
1484 {#!/bin/sh
1485 dir="`dirname "$0"`/autosetup"
1486 WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@"
1488 catch {exec chmod 755 configure}
1491 # Append the contents of $file to filehandle $f
1492 proc autosetup_install_append {f file} {
1493 set in [open $file]
1494 puts $f [read $in]
1495 close $in
1498 proc autosetup_install_file {file dir} {
1499 if {![file exists $file]} {
1500 error "Missing installation file '$file'"
1502 writefile [file join $dir [file tail $file]] [readfile $file]\n
1505 if {$::autosetup(installed)} {
1506 user-error "autosetup can only be installed from development source, not from installed copy"
1510 # ----- module markdown-formatting -----
1512 set modsource(markdown-formatting) {
1513 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1514 # All rights reserved
1516 # Module which provides text formatting
1517 # markdown format (kramdown syntax)
1519 use formatting
1521 proc para {text} {
1522 regsub -all "\[ \t\n\]+" [string trim $text] " " text
1523 regsub -all {([^a-zA-Z])'([^']*)'} $text {\1**`\2`**} text
1524 regsub -all {^'([^']*)'} $text {**`\1`**} text
1525 regsub -all {(http[^ \t\n]*)} $text {[\1](\1)} text
1526 return $text
1528 proc title {text} {
1529 underline [para $text] =
1532 proc p {text} {
1533 puts [para $text]
1536 proc codelines {lines} {
1537 puts "~~~~~~~~~~~~"
1538 foreach line $lines {
1539 puts $line
1541 puts "~~~~~~~~~~~~"
1544 proc code {text} {
1545 puts "~~~~~~~~~~~~"
1546 foreach line [parse_code_block $text] {
1547 puts $line
1549 puts "~~~~~~~~~~~~"
1552 proc nl {} {
1553 puts ""
1555 proc underline {text char} {
1556 regexp "^(\[ \t\]*)(.*)" $text -> indent words
1557 puts $text
1558 puts $indent[string repeat $char [string length $words]]
1560 proc section {text} {
1561 underline "[para $text]" -
1564 proc subsection {text} {
1565 puts "### `$text`"
1568 proc bullet {text} {
1569 puts "* [para $text]"
1571 proc defn {first args} {
1572 puts "^"
1573 set defn [string trim [join $args \n]]
1574 if {$first ne ""} {
1575 puts "**${first}**"
1576 puts -nonewline ": "
1577 regsub -all "\n\n" $defn "\n: " defn
1579 puts "$defn"
1583 # ----- module misc -----
1585 set modsource(misc) {
1586 # Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/
1587 # All rights reserved
1589 # Module containing misc procs useful to modules
1590 # Largely for platform compatibility
1592 set autosetup(istcl) [info exists ::tcl_library]
1593 set autosetup(iswin) [string equal windows $tcl_platform(platform)]
1595 if {$autosetup(iswin)} {
1596 # mingw/windows separates $PATH with semicolons
1597 # and doesn't have an executable bit
1598 proc split-path {} {
1599 split [getenv PATH .] {;}
1601 proc file-isexec {exec} {
1602 # Basic test for windows. We ignore .bat
1603 if {[file isfile $exec] || [file isfile $exec.exe]} {
1604 return 1
1606 return 0
1608 } else {
1609 # unix separates $PATH with colons and has and executable bit
1610 proc split-path {} {
1611 split [getenv PATH .] :
1613 proc file-isexec {exec} {
1614 file executable $exec
1618 # Assume that exec can return stdout and stderr
1619 proc exec-with-stderr {args} {
1620 exec {*}$args 2>@1
1623 if {$autosetup(istcl)} {
1624 # Tcl doesn't have the env command
1625 proc getenv {name args} {
1626 if {[info exists ::env($name)]} {
1627 return $::env($name)
1629 if {[llength $args]} {
1630 return [lindex $args 0]
1632 return -code error "environment variable \"$name\" does not exist"
1634 proc isatty? {channel} {
1635 dict exists [fconfigure $channel] -xchar
1637 } else {
1638 if {$autosetup(iswin)} {
1639 # On Windows, backslash convert all environment variables
1640 # (Assume that Tcl does this for us)
1641 proc getenv {name args} {
1642 string map {\\ /} [env $name {*}$args]
1644 } else {
1645 # Jim on unix is simple
1646 alias getenv env
1648 proc isatty? {channel} {
1649 set tty 0
1650 catch {
1651 # isatty is a recent addition to Jim Tcl
1652 set tty [$channel isatty]
1654 return $tty
1658 # In case 'file normalize' doesn't exist
1660 proc file-normalize {path} {
1661 if {[catch {file normalize $path} result]} {
1662 if {$path eq ""} {
1663 return ""
1665 set oldpwd [pwd]
1666 if {[file isdir $path]} {
1667 cd $path
1668 set result [pwd]
1669 } else {
1670 cd [file dirname $path]
1671 set result [file join [pwd] [file tail $path]]
1673 cd $oldpwd
1675 return $result
1678 # If everything is working properly, the only errors which occur
1679 # should be generated in user code (e.g. auto.def).
1680 # By default, we only want to show the error location in user code.
1681 # We use [info frame] to achieve this, but it works differently on Tcl and Jim.
1683 # This is designed to be called for incorrect usage in auto.def, via autosetup-error
1685 proc error-location {msg} {
1686 if {$::autosetup(debug)} {
1687 return -code error $msg
1689 # Search back through the stack trace for the first error in a .def file
1690 for {set i 1} {$i < [info level]} {incr i} {
1691 if {$::autosetup(istcl)} {
1692 array set info [info frame -$i]
1693 } else {
1694 lassign [info frame -$i] info(caller) info(file) info(line)
1696 if {[string match *.def $info(file)]} {
1697 return "[relative-path $info(file)]:$info(line): Error: $msg"
1699 #puts "Skipping $info(file):$info(line)"
1701 return $msg
1704 # If everything is working properly, the only errors which occur
1705 # should be generated in user code (e.g. auto.def).
1706 # By default, we only want to show the error location in user code.
1707 # We use [info frame] to achieve this, but it works differently on Tcl and Jim.
1709 # This is designed to be called for incorrect usage in auto.def, via autosetup-error
1711 proc error-stacktrace {msg} {
1712 if {$::autosetup(debug)} {
1713 return -code error $msg
1715 # Search back through the stack trace for the first error in a .def file
1716 for {set i 1} {$i < [info level]} {incr i} {
1717 if {$::autosetup(istcl)} {
1718 array set info [info frame -$i]
1719 } else {
1720 lassign [info frame -$i] info(caller) info(file) info(line)
1722 if {[string match *.def $info(file)]} {
1723 return "[relative-path $info(file)]:$info(line): Error: $msg"
1725 #puts "Skipping $info(file):$info(line)"
1727 return $msg
1730 # Given the return from [catch {...} msg opts], returns an appropriate
1731 # error message. A nice one for Jim and a less-nice one for Tcl.
1732 # If 'fulltrace' is set, a full stack trace is provided.
1733 # Otherwise a simple message is provided.
1735 # This is designed for developer errors, e.g. in module code or auto.def code
1738 proc error-dump {msg opts fulltrace} {
1739 if {$::autosetup(istcl)} {
1740 if {$fulltrace} {
1741 return "Error: [dict get $opts -errorinfo]"
1742 } else {
1743 return "Error: $msg"
1745 } else {
1746 lassign $opts(-errorinfo) p f l
1747 if {$f ne ""} {
1748 set result "$f:$l: Error: "
1750 append result "$msg\n"
1751 if {$fulltrace} {
1752 append result [stackdump $opts(-errorinfo)]
1755 # Remove the trailing newline
1756 string trim $result
1761 # ----- module text-formatting -----
1763 set modsource(text-formatting) {
1764 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1765 # All rights reserved
1767 # Module which provides text formatting
1769 use formatting
1771 proc wordwrap {text length {firstprefix ""} {nextprefix ""}} {
1772 set len 0
1773 set space $firstprefix
1774 foreach word [split $text] {
1775 set word [string trim $word]
1776 if {$word == ""} {
1777 continue
1779 if {$len && [string length $space$word] + $len >= $length} {
1780 puts ""
1781 set len 0
1782 set space $nextprefix
1784 incr len [string length $space$word]
1786 # Use man-page conventions for highlighting 'quoted' and *quoted*
1787 # single words.
1788 # Use x^Hx for *bold* and _^Hx for 'underline'.
1790 # less and more will both understand this.
1791 # Pipe through 'col -b' to remove them.
1792 if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1793 regsub -all . $bareword "_\b&" word
1794 append word $dot
1795 } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} {
1796 regsub -all . $bareword "&\b&" word
1797 append word $dot
1799 puts -nonewline $space$word
1800 set space " "
1802 if {$len} {
1803 puts ""
1806 proc title {text} {
1807 underline [string trim $text] =
1810 proc p {text} {
1811 wordwrap $text 80
1814 proc codelines {lines} {
1815 foreach line $lines {
1816 puts " $line"
1820 proc nl {} {
1821 puts ""
1823 proc underline {text char} {
1824 regexp "^(\[ \t\]*)(.*)" $text -> indent words
1825 puts $text
1826 puts $indent[string repeat $char [string length $words]]
1828 proc section {text} {
1829 underline "[string trim $text]" -
1832 proc subsection {text} {
1833 underline "$text" ~
1836 proc bullet {text} {
1837 wordwrap $text 76 " * " " "
1839 proc indent {text} {
1840 wordwrap $text 76 " " " "
1842 proc defn {first args} {
1843 if {$first ne ""} {
1844 underline " $first" ~
1846 foreach p $args {
1847 if {$p ne ""} {
1848 indent $p
1854 # ----- module wiki-formatting -----
1856 set modsource(wiki-formatting) {
1857 # Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/
1858 # All rights reserved
1860 # Module which provides text formatting
1861 # wiki.tcl.tk format output
1863 use formatting
1865 proc joinlines {text} {
1866 set lines {}
1867 foreach l [split [string trim $text] \n] {
1868 lappend lines [string trim $l]
1870 join $lines
1872 proc p {text} {
1873 puts [joinlines $text]
1874 puts ""
1876 proc title {text} {
1877 puts "*** [joinlines $text] ***"
1878 puts ""
1880 proc codelines {lines} {
1881 puts "======"
1882 foreach line $lines {
1883 puts " $line"
1885 puts "======"
1887 proc code {text} {
1888 puts "======"
1889 foreach line [parse_code_block $text] {
1890 puts " $line"
1892 puts "======"
1894 proc nl {} {
1896 proc section {text} {
1897 puts "'''$text'''"
1898 puts ""
1900 proc subsection {text} {
1901 puts "''$text''"
1902 puts ""
1904 proc bullet {text} {
1905 puts " * [joinlines $text]"
1907 proc indent {text} {
1908 puts " : [joinlines $text]"
1910 proc defn {first args} {
1911 if {$first ne ""} {
1912 indent '''$first'''
1915 foreach p $args {
1916 p $p
1922 ##################################################################
1924 # Entry/Exit
1926 if {$autosetup(debug)} {
1927 main $argv
1929 if {[catch {main $argv} msg opts] == 1} {
1930 show-notices
1931 autosetup-full-error [error-dump $msg $opts $::autosetup(debug)]
1932 if {!$autosetup(debug)} {
1933 puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace"
1935 exit 1