#!/usr/opt/bin/tclsh
if {!$argc} {puts {Usage: $argv0 TeXfile args
TeXfile contains TeX code with embedded Tcl code.
args are optional arguments passed to the Tcl code.
It outputs to stdout TeX code.
For more info see comments in the script.}
exit 1}
# gives index of first occurrence of $char in $str after $i not preceded by \
proc txl_strf {char str i} {
while {[set j [string first $char $str $i]] >= 0} {
set i [expr $j+1]
if {[string index $str [expr $j-1]] eq "\\"} {continue}
return $j}
return -1}
# puts $ln, %$xy/ is substituted with $xy, %\xy/ runs xy and is not put.
# / in xy can be escaped as \/, then it does not terminate input of xy.
# % can be escaped as \% (\%$xy/ or \%\xy/ is just put without side effect),
# other %s is put and leads to no more processing.
proc txl_procln {ln} {
set n 0
set i 0
while {[set j [txl_strf % $ln $i]] >= 0} {
puts -nonewline [string range $ln $i [expr $j-1]]
set i [expr $j+1]
set k [txl_strf / $ln $i]
if {$k < 0 || $k==$i} {incr i -1; break}
set c [string map {\/ /} [string range $ln [expr $i+1] [expr $k-1]]]
switch [string index $ln $i] {
\$ {incr n; uplevel #0 "puts -nonewline \[set \"$c\"\]"}
\\ {incr n; uplevel #0 $c}
default {incr i -1; break}}
set i [expr $k+1]}
puts [string range $ln $i end]
return $n}
# Collect succesive lines beginning with %% and pass them without the %% to
# the tcl interpreter when it finds a line not beginning with %%.
# Lines not beginning with %% are passed to txl_procln
proc txl_proctxt {file} {
global argv
set chan [open $file r]
set cod ""
set mod 0
while {[gets $chan ln] >= 0} {
if {[string range $ln 0 1] eq "%%"} {
set mod 1; append cod [string range $ln 2 end] \n
} else {
if {$mod} {set mod 0; uplevel #0 $cod; set cod ""}
regexp {^\\(\\*%%.*)$} $ln match ln
txl_procln $ln}}
close $chan}
# Now execute
set txl_file [lindex $argv 0]
set txl_fileroot [file rootname $txl_file] ;# may be needed for creating files
txl_proctxt $txl_file
# Copyright (c) 2022-2026 Rodrigo Readi <hruodr@gmail.com>