#!/bin/sh
# the next line restarts using the interpreter \
exec tclsh "$0" "$@"

# $Id: source.tcl,v 1.20 2005/05/28 10:09:13 jfontain Exp $

# This utility can be used to combine all sourced files making a Tcl
# program into a single file, so that the source command is no longer
# required for the program to run.

# This is most useful for creating tclets (Tcl applets) running within
# the Tcl plug-in, which, as a safe interpreter, does not allow files to
# be sourced by default (read the Tcl plugin faq for ways to allow
# sourcing files).

# type "source.tcl -h" for usage.

proc sourceCode {fileName} {
    global sourced directories duplicates withGUI

    if {!$duplicates && [info exists sourced($fileName)]} {
        return {}                 ;# do not process the same file more than once
    }
    set sourced($fileName) {}

    set code {}
    if {[string length $fileName] == 0} {
        set file stdin
    } else {
        if {[string match /* $fileName]} {
            set file [open $fileName]
        } else {
            foreach directory $directories {      ;# search multiple directories
                if {![catch {set file [open $directory/$fileName]}]} break
            }
        }
        if {![info exists file]} {
            puts stderr "could not find file $fileName"
            exit 1
        }
    }
    # look for own RCS identification in file (use ascii code for $ so that RCS
    # does not mess up regular expression when checking in this file
    set strip\
        [regexp -line {\044Id: [^\044]+ jfontain [^\044]+ \044} [read $file]]
    seek $file 0
    set cut 0
    while {[gets $file line] >= 0} {
        if {[string match {*\\} $line]} {
            append continued [string trimright $line \\]
            continue
        }
        if {[info exists continued]} {
            append continued $line
            set line $continued
            unset continued
        }
        switch -regexp -- $line {
            {^if\s+\{\$(::)?(global::)?withGUI\}\s+\{\s+;#\s+>8} {
                # start of GUI related code
                set cut [expr {!$withGUI}]
                continue
            }
            {^if\s+\{!\$(::)?(global::)?withGUI\}\s+\{\s+;#\s+>8} {
                # start of daemon related code
                set cut $withGUI
                continue
            }
            {^\}\s+else\s+\{\s+;#\s+>8} {
                # transition between specific code sections
                set cut [expr {!$cut}]
                continue
            }
            {^\}\s+;#\s+>8} {                    ;# end of specific code
                set cut 0
                continue
            }
        }
        if {$cut} continue
        if {$strip} {
            # since this is one of our own source files, it is safe to strip
            # comments from it
            if {[regexp {^[ 	]*#} $line]} continue
            # remove trailing comments or blanks on terminated lines
            regsub {;#.*$} $line {} line
            regsub {\s+$} $line {} line
        }
        if {[scan $line { source %s} name] > 0} {
            append code [sourceCode [subst $name]]
            continue
        }
        append code $line\n
    }
    if {[string length $fileName] > 0} {
        close $file
    }
    return $code
}

if {[string match -h* [lindex $argv 0]]} {
    puts "usage: $argv0 \[-d\] \[-g\] \[-I directory\] \[-o outputFile\] \[inputFile\]"
    exit
}

set duplicates 0
set output stdout
# always start with current directory for files included through the source
# command facility
set directories .
set withGUI 0

foreach {option value} $argv {
    switch -- $option {
        -d {set duplicates $value}
        -g {set withGUI $value}
        -I {lappend directories $value}
        -o {set output [open $value w]}
    }
}

puts $output [sourceCode [lindex $argv end]]
close $output
