diff options
author | Steve Bennett <steveb@workware.net.au> | 2019-05-20 15:36:32 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2019-07-01 11:14:58 +1000 |
commit | 822df774aa79cbd4738ebf2624c7dbffe2ca26d9 (patch) | |
tree | 1e7773b529799e3ecd30cddbb9562e7f64c29c40 /autosetup/system.tcl | |
parent | 376414498fc647ef10346c27f725083b35a45bd1 (diff) | |
download | jimtcl-822df774aa79cbd4738ebf2624c7dbffe2ca26d9.zip jimtcl-822df774aa79cbd4738ebf2624c7dbffe2ca26d9.tar.gz jimtcl-822df774aa79cbd4738ebf2624c7dbffe2ca26d9.tar.bz2 |
Update autosetup to v0.6.9
Diffstat (limited to 'autosetup/system.tcl')
-rw-r--r-- | autosetup/system.tcl | 173 |
1 files changed, 111 insertions, 62 deletions
diff --git a/autosetup/system.tcl b/autosetup/system.tcl index 37377eb..b98b5c0 100644 --- a/autosetup/system.tcl +++ b/autosetup/system.tcl @@ -133,6 +133,102 @@ proc write-if-changed {file buf {script {}}} { } } + +# @include-file infile mapping +# +# The core of make-template, called recursively for each @include +# directive found within that template so that this proc's result +# is the fully-expanded template. +# +# The mapping parameter is how we expand @varname@ within the template. +# We do that inline within this step only for @include directives which +# can have variables in the filename arg. A separate substitution pass +# happens when this recursive function returns, expanding the rest of +# the variables. +# +proc include-file {infile mapping} { + # A stack of true/false conditions, one for each nested conditional + # starting with "true" + set condstack {1} + set result {} + set linenum 0 + foreach line [split [readfile $infile] \n] { + incr linenum + if {[regexp {^@(if|else|endif)(\s*)(.*)} $line -> condtype condspace condargs]} { + if {$condtype eq "if"} { + if {[string length $condspace] == 0} { + autosetup-error "$infile:$linenum: Invalid expression: $line" + } + if {[llength $condargs] == 1} { + # ABC => [get-define ABC] ni {0 ""} + # !ABC => [get-define ABC] in {0 ""} + lassign $condargs condvar + if {[regexp {^!(.*)} $condvar -> condvar]} { + set op in + } else { + set op ni + } + set condexpr "\[[list get-define $condvar]\] $op {0 {}}" + } else { + # Translate alphanumeric ABC into [get-define ABC] and leave the + # rest of the expression untouched + regsub -all {([A-Z][[:alnum:]_]*)} $condargs {[get-define \1]} condexpr + } + if {[catch [list expr $condexpr] condval]} { + dputs $condval + autosetup-error "$infile:$linenum: Invalid expression: $line" + } + dputs "@$condtype: $condexpr => $condval" + } + if {$condtype ne "if"} { + if {[llength $condstack] <= 1} { + autosetup-error "$infile:$linenum: Error: @$condtype missing @if" + } elseif {[string length $condargs] && [string index $condargs 0] ne "#"} { + autosetup-error "$infile:$linenum: Error: Extra arguments after @$condtype" + } + } + switch -exact $condtype { + if { + # push condval + lappend condstack $condval + } + else { + # Toggle the last entry + set condval [lpop condstack] + set condval [expr {!$condval}] + lappend condstack $condval + } + endif { + if {[llength $condstack] == 0} { + user-notice "$infile:$linenum: Error: @endif missing @if" + } + lpop condstack + } + } + continue + } elseif {[regexp {^@include\s+(.*)} $line -> filearg]} { + set incfile [string map $mapping $filearg] + if {[file exists $incfile]} { + lappend ::autosetup(deps) [file-normalize $incfile] + lappend result {*}[include-file $incfile $mapping] + } else { + user-error "$infile:$linenum: Include file $incfile is missing" + } + continue + } elseif {[regexp {^@define\s+(\w+)\s+(.*)} $line -> var val]} { + define $var $val + continue + } + # Only output this line if the stack contains all "true" + if {"0" in $condstack} { + continue + } + lappend result $line + } + return $result +} + + # @make-template template ?outfile? # # Reads the input file '<srcdir>/$template' and writes the output file '$outfile' @@ -195,70 +291,23 @@ proc make-template {template {out {}}} { define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] define top_srcdir [relative-path $::autosetup(srcdir) $outdir] - set mapping {} - foreach {n v} [array get ::define] { - lappend mapping @$n@ $v - } - - # A stack of true/false conditions, one for each nested conditional - # starting with "true" - set condstack {1} - set result {} - set linenum 0 - foreach line [split [readfile $infile] \n] { - incr linenum - if {[regexp {^@(if|else|endif)\s*(.*)} $line -> condtype condargs]} { - if {$condtype eq "if"} { - if {[llength $condargs] == 1} { - # ABC => [get-define ABC] ni {0 ""} - # !ABC => [get-define ABC] in {0 ""} - lassign $condargs condvar - if {[regexp {^!(.*)} $condvar -> condvar]} { - set op in - } else { - set op ni - } - set condexpr "\[[list get-define $condvar]\] $op {0 {}}" - } else { - # Translate alphanumeric ABC into [get-define ABC] and leave the - # rest of the expression untouched - regsub -all {([A-Z][[:alnum:]_]*)} $condargs {[get-define \1]} condexpr - } - if {[catch [list expr $condexpr] condval]} { - dputs $condval - autosetup-error "$infile:$linenum: Invalid expression: $line" - } - dputs "@$condtype: $condexpr => $condval" - } - if {$condtype ne "if" && [llength $condstack] <= 1} { - autosetup-error "$infile:$linenum: Error: @$condtype missing @if" - } - switch -exact $condtype { - if { - # push condval - lappend condstack $condval - } - else { - # Toggle the last entry - set condval [lpop condstack] - set condval [expr {!$condval}] - lappend condstack $condval - } - endif { - if {[llength $condstack] == 0} { - user-notice "$infile:$linenum: Error: @endif missing @if" - } - lpop condstack - } - } - continue + # Build map from global defines to their values so they can be + # substituted into @include file names. + proc build-define-mapping {} { + set mapping {} + foreach {n v} [array get ::define] { + lappend mapping @$n@ $v } - # Only output this line if the stack contains all "true" - if {"0" in $condstack} { - continue - } - lappend result $line + return $mapping } + set mapping [build-define-mapping] + + set result [include-file $infile $mapping] + + # Rebuild the define mapping in case we ran across @define + # directives in the template or a file it @included, then + # apply that mapping to the expanded template. + set mapping [build-define-mapping] write-if-changed $out [string map $mapping [join $result \n]] { msg-result "Created [relative-path $out] from [relative-path $template]" } |