# This tcl script generates a makefile suitable for programs that
# use the Tcl/Tk library.
#
# This script begins life as "makemake.tcl.in".  A "configure"
# shell script will read "makemake.tcl.in" and generate
# "makemake.tcl".  The makemake.tcl script then runs to
# produce the makefile.
#
# Both this script and the "configure.in" script are general purpose
# and can be easily adapted to many different projects.  The
# "configure.in" script will require little or not customization.
# (Prehaps comment out the BLT part if you are not using BLT.)
# This script requires some customization down toward the bottom.
#
# $Revision: 1.8 $
#

# Some useful variables.
#
set SHLIB         [list @ENABLE_SHLIB@]
set TOP           [list @srcdir@]
set BTCLSH        [list @BUILD_TCLSH@]
set BEXE          [list @BUILD_EXEEXT@]
set TEXE          [list @TARGET_EXEEXT@]
set PFX           [list @program_prefix@]
set prefix        [list @prefix@]
set exec_prefix   [list @exec_prefix@]
set BINDIR        [list @bindir@]
set LIBDIR	  [file join @libdir@ Tkhtml]

# Remove surplus ".." and "." elements from a pathname.
#
proc CleanPath path {
  regsub -all {/\./} $path / path
  while {[regsub -all {[^/]*[^/.]/\.\./} $path {} path]} {}
  return $path
}

# This procedure returns a pathname relative to the directory
# we are compiling in, for a file whose name is relative to the
# top of the source directory.
#
# Example:  If the source tree is at /home/src/progZ and we
# are compiling in /home/tmp/progZ, then
#
#     Src src/file1.c
#
# returns
#
#     ../../src/progZ/src/file1.c
#
proc Src rel {
  if {[file pathtype $rel]=="relative"} {
    set result [CleanPath @srcdir@/$rel]
  } else {
    set result $rel
  }
  return $result
}

# Convert a pathname to an absolute pathname.
#
proc AbsPath path {
  switch [file pathtype $path] {
    absolute {
      set path [CleanPath $path]
    }
    relative {
      set path [CleanPath [pwd]/$path]
    }
    default {
    }
  }
  return $path
}

# Remove surplus white-space from the named
# variable.
#
proc Strip varname {
  upvar 1 $varname v
  regsub -all "\[ \t\n\r\]\[ \t\n\r\]*" [string trim $v] { } v
}

# Generate a C program that runs on the host machine.  The input
# is C source code.  This routine is used to build utilities that
# are used in the build process.  Examples: makeheaders, mktclapp,
# help2tk, lemon, etc.
#
proc MakeTool {name src {libs {}}} {
  global BEXE
  set n "${name}$BEXE"
  puts "$n:	$src"
  puts "	@BUILD_CC@ @BUILD_CFLAGS@ -o $n $src $libs"
  puts ""
  global cleanable; lappend cleanable $n
}

# Generate an executable that will run on the target machine.
# The inputs are *.o files, *.c files and locally built libraries.
#
# The optional 3rd argument specifies what Tcl/Tk libraries the
# executable should be linked against.  The 3rd argument should be
# one of the following keywords: "blt", "tk", "tcl".  Or it can
# be blank.
#
proc MakeProg {name obj {libs {tk}}} {
  global TEXE PFX
  set n "${PFX}${name}$TEXE"
  switch $libs {
    tcl {
      set link "@TARGET_CC@ @TARGET_CFLAGS@ -I. @TARGET_TCL_INC@"
      append link " @TARGET_X_INC@"
      set lib "@TARGET_TCL_LIBS@ @TARGET_LIBS@"
    }
    tk {
      set link "@TARGET_CC@ @TARGET_CFLAGS@ -I. @TARGET_TCL_INC@"
      append link " @TARGET_X_INC@"
      append link " @TARGET_TK_INC@"
      set lib "@TARGET_TK_LIBS@ @TARGET_X_LIBS@ @TARGET_TCL_LIBS@ @TARGET_LIBS@"
    }
    blt {
      set link "@TARGET_CC@ @TARGET_CFLAGS@ -I. @TARGET_TCL_INC@"
      append link " @TARGET_X_INC@"
      append link " @TARGET_TK_INC@ @TARGET_BLT_INC@"
      set lib "@TARGET_BLT_LIBS@ @TARGET_TK_LIBS@ @TARGET_TCL_LIBS@"
      append lib " @TARGET_X_LIBS@ @TARGET_LIBS@"
    }
    default {
      set link "@TARGET_CC@ @TARGET_CFLAGS@ -I."
      append link " @TARGET_X_INC@"
      set lib $libs
    }
  }
  puts "$n:	$obj"
  puts "	$link -o $n $obj $lib"
  puts ""
  global cleanable; lappend cleanable $n
  global exelist; lappend exelist $n
}

# Convert C source code into a *.o file that can be used in a
# shared library.  The optional 3rd argument is a list of extra
# dependencies for this target.
#
# An "sh" prefix is added to the generated *.o file.
#
proc MakeShObj {name src {dep {}}} {
  if {"@ENABLE_SHLIB@"!=1} return
  set n sh$name
  set cc "@TARGET_CC@ @TARGET_SHLIB_CFLAGS@ -I. @TARGET_TCL_INC@"
  append cc " @TARGET_X_INC@"
  append cc " @TARGET_TK_INC@ @TARGET_BLT_INC@"
  puts "$n:	$src $dep"
  puts "	$cc -o $n -c $src"
  puts ""
  global cleanable; lappend cleanable $n
}

# Generate a shared library from *.o files that were prepared using
# the MakeShObj function above.
#
# The optional 3rd argument specifies what Tcl/Tk libraries the
# shared library should be linked against.  The 3rd argument should
# be one of the following keywords: "blt", "tk", "tcl".  Or it can
# be blank.
#
proc MakeShLib {name obj {libs tk}} {
  if {"@ENABLE_SHLIB@"!=1} return
  set n "$name@TARGET_SHLIB_EXT@"
  set link {@TARGET_SHLIB_LINK@}
  switch $libs {
    tcl {
      set lib "@TARGET_TCL_LIBS@ @TARGET_LIBS@"
    }
    tk {
      set lib "@TARGET_TK_LIBS@ @TARGET_X_LIBS@ @TARGET_TCL_LIBS@ @TARGET_LIBS@"
    }
    blt {
      set lib "@TARGET_BLT_LIBS@ @TARGET_TK_LIBS@ @TARGET_TCL_LIBS@"
      append lib " @TARGET_X_LIBS@ @TARGET_LIBS@"
    }
  }
  set shobj {}
  foreach f $obj {
    lappend shobj sh$f
  }
  puts "$n:	$shobj"
  puts "	$link -o $n $shobj $lib"
  puts ""
  global cleanable; lappend cleanable $n
}

# Convert C source code into a *.o file that can be used in a
# static library.
#
proc MakeObj {name src {dep {}}} {
  set n $name
  set cc "@TARGET_CC@ @TARGET_CFLAGS@ -I. @TARGET_TCL_INC@"
  append cc " @TARGET_X_INC@"
  append cc " @TARGET_TK_INC@ @TARGET_BLT_INC@"
  puts "$n:	$src $dep"
  puts "	$cc -o $n -c $src"
  puts ""
  global cleanable; lappend cleanable $n
}

# Generate a static library from *.o files that were prepared using
# the MakeObj function above.
#
proc MakeLib {name obj} {
  set n $name.a
  puts "$n:	$obj"
  puts "	@TARGET_AR@ $n $obj"
  set ranlib [list @TARGET_RANLIB@]
  if {[string length $ranlib]>0} {
    puts "	$ranlib $n"
  }
  puts ""
  global cleanable; lappend cleanable $n
}

# Generate rules for a *.mta file, a *.h file and a *.c file for the
# given application initialization file.  Here are the parameters:
#
#   name      The base name of the generated files.  The following
#             files will be generated:
#                ${name}.mta
#                ${name}.c
#                ${name}.h
#                ${name}.o
#                ${name}dev.mta
#                ${name}dev.c
#                ${name}dev.h
#                ${name}dev.o
#
#   main      The name of the main TCL script.  May be {}
#
#   alltcl    The names of all TCL scripts.
#
#   allc      The names of all C source files that mktclapp needs to
#             read to discover ET_COMMAND_ and Et_AppInit functions.
#
#   mode      Either of two keywords: "tcl" or "tk".
#
#   options   Any additional options to pass to mktclapp.  Example: -console
#
proc MakeMta {name main alltcl allc mode options} {
  global cleanable BEXE
  set n ${name}dev.mta
  puts "$n:	"
  puts "	echo ' -tcl-library @TARGET_TCL_SCRIPT_DIR@' >$n"
  if {$mode=="tk"} {
    puts "	echo ' -tk-library @TARGET_TK_SCRIPT_DIR@' >>$n"
  }
  if {$main!=""} {
    puts "	echo ' -main-script $main' >>$n"
  }
  if {$options!=""} {
    puts "	echo ' $options' >>$n"
  }
  puts "	echo ' $allc' >>$n"
  puts ""
  lappend cleanable $n
  puts "${name}dev.c:	$n mktclapp$BEXE"
  puts "	./mktclapp$BEXE -f $n >${name}dev.c"
  puts ""
  lappend cleanable ${name}dev.c
  puts "${name}dev.h:	mktclapp$BEXE"
  puts "	./mktclapp$BEXE -header >${name}dev.h"
  puts ""
  lappend cleanable ${name}dev.h
  MakeObj ${name}dev.o ${name}dev.c
  set n ${name}.mta
  puts "$n:	${name}dev.mta"
  puts "	cat ${name}dev.mta >$n"
  puts "	echo ' $alltcl' >>$n"
  puts "	echo @TARGET_TCL_SCRIPT_DIR@/*.tcl >>$n"
  puts "	echo '@TARGET_TCL_SCRIPT_DIR@/tclIndex' >>$n"
  if {$mode=="tk"} {
    puts "	echo @TARGET_TK_SCRIPT_DIR@/*.tcl >>$n"
    puts "	echo '@TARGET_TK_SCRIPT_DIR@/tclIndex' >>$n"
  }
  puts ""
  lappend cleanable $n
  puts "$name.c:	$n $allc $alltcl mktclapp$BEXE"
  puts "	./mktclapp$BEXE -f $n >$name.c"
  puts ""
  lappend cleanable $name.c
  puts "$name.h:	${name}dev.h"
  puts "	cp ${name}dev.h $name.h"
  puts ""
  lappend cleanable $name.h
  MakeObj $name.o $name.c
}

# Write an introduction to the generated makefile.
# 
puts "# Automatically generated by makemake.tcl"
puts "# Do Not Edit!"
puts ""

puts ".NOTPARALLEL :"

#############################################################################
#              CUSTOMIZE BELOW THIS LINE
#
# The stuff the follows is specific to each individual project and
# should be customized.  Edit below this line.  Do not edit above
# this line.
#

# Put the basename of each C source code modules
# here.  Omit the ".c" suffix.
#
set srcc {
  src/htmlcmd
  src/htmldraw
  src/htmlform
  src/htmlimage
  src/htmlindex
  src/htmllayout
  src/htmlparse
  src/htmlsizer
  src/htmltable
  src/htmltest
  src/htmlurl
  src/htmlwidget
  src/htmlexts
}

# Put the names of all TCL source files here.  Include the ".tcl"
# suffix.
#
set srctcl {
}

# Put here the basenames of all C code modules that are
# generated by helper programs or/and automated scripts.  These
# files are C code but they are not source code. 
# Omit the ".c" suffix.
#
set autoc {
  htmltokens
}

# Put here the names of all TCL code modules that are
# generated by helper programs and/or scripts.  Include the
# ".tcl" suffix.
#
set autotcl {
}

# Remove surplus whitespace from the lists of files defined above.
#
Strip srcc
Strip srctcl
Strip autoc
Strip autotcl

# A target to build everything.
#
set all ${PFX}hwish${TEXE}
lappend all ${PFX}hv${TEXE}
lappend all ${PFX}ss${TEXE}
if {"@ENABLE_SHLIB@"=="1"} {
  lappend all tkhtml@TARGET_SHLIB_EXT@
#  lappend all tkhtml.so
  lappend all pkgIndex.tcl
}
puts "all:	headers $all"
puts ""

# Compile host-side utilities
#
MakeTool makeheaders [Src tools/makeheaders.c]
MakeTool mktclapp [Src tools/mktclapp.c]

# Generate the htmltokens.c file
#
puts "htmltokens.c:	[Src src/tokenlist.txt] [Src tools/maketokens.tcl]"
if {$BEXE == ".exe"} {
puts "\t$BTCLSH \'[exec cygpath -w [Src tools/maketokens.tcl]]\' \'[exec cygpath -w [Src src/tokenlist.txt]]\' >htmltokens.c"
} else {
puts "\t$BTCLSH [Src tools/maketokens.tcl] [Src src/tokenlist.txt] >htmltokens.c"
}
puts ""
lappend cleanable htmltokens.c

# Generate the pkgIndex.tcl file
#
puts "pkgIndex.tcl:	tkhtml@TARGET_SHLIB_EXT@"
#puts "pkgIndex.tcl:	tkhtml.so"
puts "\techo 'pkg_mkIndex . tkhtml.@TARGET_SHLIB_EXT@' | $BTCLSH"
#puts "\techo 'pkg_mkIndex . tkhtml.so' | $BTCLSH"
puts ""
lappend cleanable pkgIndex.tcl

# The main library
#
set obj {}
set shobj {}
foreach f $srcc {
  set m [file tail $f]
  lappend obj $m.o
  MakeObj $m.o [Src $f.c] $m.h
  MakeShObj $m.o [Src $f.c] $m.h
}
foreach f $autoc {
  lappend obj $f.o
  MakeObj $f.o $f.c $f.h
  MakeShObj $f.o $f.c $f.h
}
MakeLib libtkhtml $obj
MakeShLib tkhtml $obj

# Header files for the library objects and for the library itself.
#
set mharg {}
foreach f $srcc {
  set m [file tail $f]
  lappend mharg [Src $f.c]:$m.h
  lappend cleanable $m.h
}
foreach f $autoc {
  lappend mharg $f.c
  lappend cleanable $f.h
}
puts "headers:	makeheaders$BEXE htmltokens.c"
puts "	./makeheaders$BEXE $mharg [Src src/html.h]"
puts ""
puts "[lindex $srcc 0].h:	headers"
puts ""

# The install routine for the shared library
#
puts "install-lib:	pkgIndex.tcl"
puts "	if test ! -d $LIBDIR; then mkdir $LIBDIR; fi"
puts "	cp tkhtml@TARGET_SHLIB_EXT@ $LIBDIR"
#puts "	cp tkhtml.so $LIBDIR"
puts "	cp pkgIndex.tcl $LIBDIR"
puts ""

# Create two MTA files for appinit.c and appinitdev.c.  The first
# has all scripts compiled in and the second does not.  The first
# is suitable for shipping as a standalone executable and the
# second is designed for testing.
#
set alltcl {}
foreach f [concat $srctcl $autotcl] {
  lappend alltcl $f
}
if {$TEXE==".exe"} {
  set options {-console}
} else {
  set options {-read-stdin}
}
MakeMta appinit [lindex $srctcl 0] $alltcl [Src src/htmlwish.c] tk $options

# Now generate hwish and hwishdev
#
MakeObj htmlwish.o [Src src/htmlwish.c] appinit.h
MakeProg hwish "htmlwish.o appinit.o libtkhtml.a" tk
MakeProg hwishdev "htmlwish.o appinitdev.o libtkhtml.a" tk

# Generate the "hv" application.
#
MakeMta hv [Src hv/hv.tcl] [Src hv/hv.tcl] [Src hv/hvinit.c] tk {}
MakeObj hvinit.o [Src hv/hvinit.c] hv.h
MakeProg hv "hv.o hvinit.o libtkhtml.a" tk
MakeProg hvdev "hvdev.o hvinit.o libtkhtml.a" tk

# Generate the "ss" application.
#
MakeMta ss [Src hv/ss.tcl] [Src hv/ss.tcl] [Src hv/ssinit.c] tk {}
MakeObj ssinit.o [Src hv/ssinit.c] ss.h
MakeProg ss "ss.o ssinit.o libtkhtml.a" tk
MakeProg ssdev "ssdev.o ssinit.o libtkhtml.a" tk

# This target makes a directory named "srcdir" and puts all the
# source files there.  It also generates the headers and
# automatically generated source files.
#
set srclist {}
foreach f $srcc {
  lappend srclist [Src $f.c]
}
foreach f $autoc {
  lappend srclist $f.c
}
puts "srcdir:	makeheaders$BEXE $srclist"
puts "	mkdir srcdir || true"
lappend srclist [Src src/html.h]
puts "	cp $srclist srcdir"
puts "	cd srcdir; ../makeheaders$BEXE *.\[ch\]"
puts ""

# Build the "getpage" utility
#
set srclist {getpage url sgmlparse httpget}
set mharg {}
set obj {}
foreach f $srclist {
  lappend mharg "[Src tools/$f.c]:$f.h"
  lappend obj $f.o
  MakeObj $f.o [Src tools/$f.c] $f.h
  puts "$f.h:	getpage_headers"
  puts ""
}
puts "getpage_headers:	makeheaders"
puts "	./makeheaders $mharg"
puts ""
MakeProg getpage $obj {}


puts "publish:	"
puts "	tclsh [Src webpage/mkwebpage.tcl]"
puts "	#"
puts "	# Run \"sh publish.sh\" to send web materials to the website"
puts "	#"
puts ""

#############################################################################
#  It is not usually necessary to change anything below this line.
#

# The usual makefile targets...
#
puts "clean:	"
puts "	rm -f $cleanable"
puts "	rm -rf srcdir"
puts ""
puts "distclean:	clean"
puts "	rm -f Makefile makemake.tcl config.cache config.log config.status"
puts ""
set BINDIR ../install
puts "install:	all"
puts "	if test ! -d $BINDIR; then mkdir $BINDIR; fi"
puts "	for i in $exelist; do cp \$\$i $BINDIR; strip $BINDIR/\$\$i; done"
puts ""
