From 2129e59b313d0a032b7b6eb3dab287dd32437ef9 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Thu, 16 Nov 2006 12:02:00 +0100
Subject: stable 2006.11.16 12:02

---
 scripts/context/perl/mptopdf.pl          |   4 +-
 scripts/context/perl/texfont.pl          | 525 ++++++++++++++++++++---------
 scripts/context/ruby/base/ctx.rb         |  33 +-
 scripts/context/ruby/base/kpse.rb        |  41 ++-
 scripts/context/ruby/base/kpsefast.rb    |   2 +
 scripts/context/ruby/base/mp.rb          |   4 +-
 scripts/context/ruby/base/tex.rb         | 196 ++++++++++-
 scripts/context/ruby/base/texutil.rb     |  37 ++-
 scripts/context/ruby/concheck.rb         |  56 ++--
 scripts/context/ruby/ctxtools.rb         | 553 ++++++++++++++++++++++---------
 scripts/context/ruby/pdftools.rb         |   5 +-
 scripts/context/ruby/pstopdf.rb          |   2 +-
 scripts/context/ruby/rlxtools.rb         |  66 +++-
 scripts/context/ruby/texexec.rb          |  83 ++++-
 scripts/context/ruby/texmfstart.rb       | 102 +++---
 scripts/context/ruby/texsync.rb          |   5 +-
 scripts/context/ruby/textools.rb         |   5 +-
 scripts/context/ruby/texutil.rb          |   5 +-
 scripts/context/ruby/tmftools.rb         |   5 +-
 scripts/context/ruby/www/exa.rb          |   4 +-
 scripts/context/ruby/www/lib.rb          |  15 +-
 scripts/context/ruby/wwwclient.rb        |   2 +-
 scripts/context/ruby/wwwserver.rb        |   2 +-
 scripts/context/ruby/wwwwatch.rb         |  22 +-
 scripts/context/ruby/xmltools.rb         |  11 +-
 scripts/context/stubs/mswin/luatools.bat |   2 +
 scripts/context/stubs/mswin/mtxtools.bat |   2 +
 scripts/context/stubs/unix/luatools      |   2 +
 scripts/context/stubs/unix/mtxtools      |   2 +
 29 files changed, 1305 insertions(+), 488 deletions(-)
 create mode 100755 scripts/context/stubs/mswin/luatools.bat
 create mode 100755 scripts/context/stubs/mswin/mtxtools.bat
 create mode 100755 scripts/context/stubs/unix/luatools
 create mode 100755 scripts/context/stubs/unix/mtxtools

(limited to 'scripts')

diff --git a/scripts/context/perl/mptopdf.pl b/scripts/context/perl/mptopdf.pl
index f85c36891..b1589a9d3 100644
--- a/scripts/context/perl/mptopdf.pl
+++ b/scripts/context/perl/mptopdf.pl
@@ -120,9 +120,9 @@ foreach my $file (@files) {
     $_ = $file ;
     if (s/\.(\d+|mps)$// && -e $file) {
         if ($miktex) {
-            $command = "pdfetex -undump=mptopdf" ;
+            $command = "pdftex -undump=mptopdf" ;
         } else {
-            $command = "pdfetex  -fmt=mptopdf -progname=context" ;
+            $command = "pdftex -fmt=mptopdf -progname=context" ;
         }
         if ($dosish) {
             $command = "$command \\relax $file" ;
diff --git a/scripts/context/perl/texfont.pl b/scripts/context/perl/texfont.pl
index 425417374..ec875e5b4 100644
--- a/scripts/context/perl/texfont.pl
+++ b/scripts/context/perl/texfont.pl
@@ -42,6 +42,7 @@ use Config ;
 use FindBin ;
 use File::Copy ;
 use Getopt::Long ;
+use Data::Dumper;
 
 $Getopt::Long::passthrough = 1 ; # no error message
 $Getopt::Long::autoabbrev  = 1 ; # partial switch accepted
@@ -146,6 +147,7 @@ my $trace           = 0 ;
 my $afmpl           = 0 ;
 my $trees           = 'TEXMFFONTS,TEXMFLOCAL,TEXMFEXTRA,TEXMFMAIN,TEXMFDIST' ;
 my $pattern         = '' ;
+my $uselmencodings  = 0 ;
 
 my $fontsuffix  = "" ;
 my $namesuffix  = "" ;
@@ -198,6 +200,7 @@ my @cleanup         = () ;    # atl: build list of generated files to delete
     "expert"       => \$expert,
     "afmpl"        => \$afmpl,
     "afm2pl"       => \$afmpl,
+    "lm"           => \$uselmencodings,
     "rootlist=s"   => \$trees,
     "pattern=s"    => \$pattern,
     "trace"        => \$trace,    # --verbose conflicts with --ve
@@ -549,7 +552,6 @@ if ($sourcepath eq "auto") # todo uppercase root
                     foreach my $sub ("tfm","vf")
                       { foreach my $typ ("","-raw")
                           { my $nam = "$path/fonts/$sub/$vendor/$collection/$encoding$varlabel$typ-$file.$sub" ;
-                        #  { my $nam = "$path/fonts/$sub/$vendor/$collection/$encoding$varlabel$typ-$file$fontsuffix.$sub" ;
                             if (-s $nam)
                               { report ("removing : $encoding$varlabel$typ-$file.$sub") ;
                                 unlink $nam } } } }
@@ -558,11 +560,12 @@ if ($sourcepath eq "auto") # todo uppercase root
                   { report ("removing : $nam") ;
                     unlink "$nam" }
                 my $mapfile = "$encoding$varlabel-$vendor-$collection" ;
-                my $maproot = "$fontroot/fonts/map/pdftex/context";
-                if (-e "$maproot$mapfile.map")
-                  { report ("renaming : $mapfile.map -> $mapfile.bak") ;
-                    unlink "$maproot$mapfile.bak" ;
-                    rename "$maproot$mapfile.map", "$maproot$mapfile.bak" }
+				foreach my $map ("pdftex","dvips", "dvipdfm")
+                  { my $maproot = "$fontroot/fonts/map/$map/context/";
+                    if (-e "$maproot$mapfile.map")
+                       { report ("renaming : $mapfile.map -> $mapfile.bak") ;
+                         unlink "$maproot$mapfile.bak" ;
+                         rename "$maproot$mapfile.map", "$maproot$mapfile.bak" } }
                 exit }
             else
               { last } } } }
@@ -576,9 +579,13 @@ my $tfmpath = "$fontroot/fonts/tfm/$vendor/$collection" ;
 my $vfpath  = "$fontroot/fonts/vf/$vendor/$collection" ;
 my $pfbpath = "$fontroot/fonts/type1/$vendor/$collection" ;
 my $ttfpath = "$fontroot/fonts/truetype/$vendor/$collection" ;
-my $mappath = "$fontroot/fonts/map/pdftex/context" ;
+my $otfpath = "$fontroot/fonts/opentype/$vendor/$collection" ;
 my $encpath = "$fontroot/fonts/enc/dvips/context" ;
 
+sub mappath
+  { my $str = shift ;
+    return "$fontroot/fonts/map/$str/context" }
+
 # are not on local path ! ! ! !
 
 foreach my $path ($afmpath, $pfbpath)
@@ -597,20 +604,19 @@ if (($fontroot =~ /texmf\-fonts/o) || (-e "$fontroot/ls-R") || (-e "$fontroot/ls
 sub do_make_path
   { my $str = shift ;
     if ($str =~ /^(.*)\/.*?$/)
-      { do_make_path($1) }
+      { do_make_path($1); }
     mkdir $str, 0755 unless -d $str }
 
 sub make_path
   { my $str = shift ;
-    do_make_path("$fontroot/fonts") ;
-    do_make_path("$fontroot/fonts/$str") ;
-    do_make_path("$fontroot/fonts/$str/$vendor") ;
     do_make_path("$fontroot/fonts/$str/$vendor/$collection") }
 
 if ($makepath&&$install)
   { make_path ("afm") ; make_path ("type1") }
 
-do_make_path($mappath) ;
+do_make_path(mappath("pdftex")) ;
+do_make_path(mappath("dvips")) ;
+do_make_path(mappath("dvipdfm")) ;
 do_make_path($encpath) ;
 
 # now fonts/map and fonts/enc
@@ -624,21 +630,23 @@ if ($install)
 
 error ("unknown tfm path $tfmpath") unless -d $tfmpath ;
 error ("unknown vf  path $vfpath" ) unless -d $vfpath  ;
-error ("unknown map path $mappath") unless -d $mappath ;
+error ("unknown map path " . mappath("pdftex"))  unless -d mappath("pdftex");
+error ("unknown map path " . mappath("dvips"))   unless -d mappath("dvips");
+error ("unknown map path " . mappath("dvipdfm")) unless -d mappath("dvipdfm");
 
 my $mapfile = "$identifier.map" ;
 my $bakfile = "$identifier.bak" ;
 my $texfile = "$identifier.tex" ;
 
-                report  "encoding vector : $encoding" ;
+                report "encoding vector : $encoding" ;
 if ($variant) { report "encoding variant : $variant" }
                 report      "vendor name : $vendor" ;
                 report  "    source path : $sourcepath" ;
                 report  "font collection : $collection" ;
                 report  "texmf font root : $lcfontroot" ;
-                report  "pdftex map file : $mapfile" ;
+                report  "  map file name : $mapfile" ;
 
-if ($install)        { report "source path : $sourcepath" }
+if ($install) { report "source path : $sourcepath" }
 
 my $fntlist = "" ;
 
@@ -736,45 +744,74 @@ if ($install)
         copy_files("ttf",$sourcepath,$ttfpath) }
     if ($extension eq "otf")
       { make_path("truetype") ;
-	copy_files("otf",$sourcepath,$ttfpath) } }
+	    copy_files("otf",$sourcepath,$ttfpath) } }
 
 error ("no afm files found") unless @files ;
 
-my $map = my $tex = 0 ; my $mapdata = my $texdata = "" ;
-
-copy ("$mappath/$mapfile","$mappath/$bakfile") ;
-
-if (open (MAP,"<$mappath/$mapfile"))
-  { report ("extending map file : $mappath/$mapfile") ;
-    while (<MAP>) { unless (/^\%/o) { $mapdata .= $_ } }
-    close (MAP) }
-else
-  { report ("no map file at : $mappath/$mapfile") }
+sub open_mapfile
+  { my $type = shift;
+	my $mappath = mappath($type);
+    my $mapdata = "";
+	my $mapptr = undef;
+	my $fullmapfile = $mapfile;
+	$fullmapfile = "$type-$fullmapfile" unless $type eq "pdftex";
+	if ($install)
+	  { copy ("$mappath/$mapfile","$mappath/$bakfile") ; }
+    if (open ($mapptr,"<$mappath/$mapfile"))
+      { report ("extending map file : $mappath/$mapfile") ;
+        while (<$mapptr>) { unless (/^\%/o) { $mapdata .= $_ } }
+        close ($mapptr) }
+    else
+      { report ("no map file at : $mappath/$mapfile") }
+    #~ unless (open ($mapptr,">$fullmapfile") )
+do_make_path($mappath) ;
+    unless (open ($mapptr,">$mappath/$fullmapfile") )
+      { report "warning : can't open $fullmapfile" }
+    else
+      { if ($type eq "pdftex")
+          { print $mapptr "% This file is generated by the TeXFont Perl script.\n";
+            print $mapptr "%\n" ;
+            print $mapptr "% You need to add the following line to your file:\n" ;
+            print $mapptr "%\n" ;
+            print $mapptr "%   \\pdfmapfile{+$mapfile}\n" ;
+            print $mapptr "%\n" ;
+            print $mapptr "% In ConTeXt you can best use:\n" ;
+            print $mapptr "%\n" ;
+            print $mapptr "%   \\loadmapfile\[$mapfile\]\n\n" } }
+    return ($mapptr,$mapdata) ; }
+
+sub finish_mapfile
+  { my ($type, $mapptr, $mapdata ) = @_;
+	my $fullmapfile = $mapfile;
+	$fullmapfile = "$type-$fullmapfile" unless $type eq "pdftex";
+    if (defined $mapptr)
+      { report ("updating map file : $mapfile (for $type)") ;
+        while ($mapdata =~ s/\n\n+/\n/mois) {} ;
+        $mapdata =~ s/^\s*//gmois ;
+        print $mapptr $mapdata ;
+        close ($mapptr) ;
+        if ($install)
+          { copy ("$fullmapfile", mappath($type) . "/$mapfile") ; } } }
+
+
+my ($PDFTEXMAP,$pdftexmapdata)   = open_mapfile("pdftex");
+my ($DVIPSMAP,$dvipsmapdata)     = open_mapfile("dvips");
+my ($DVIPDFMMAP,$dvipdfmmapdata) = open_mapfile("dvipdfm");
+
+my $tex = 0 ;
+my $texdata = "" ;
 
 if (open (TEX,"<$texfile"))
   { while (<TEX>) { unless (/stoptext/o) { $texdata .= $_ } }
     close (TEX) }
 
-$map = open (MAP,">$mapfile") ;
 $tex = open (TEX,">$texfile") ;
 
-unless ($map) { report "warning : can't open $mapfile" }
 unless ($tex) { report "warning : can't open $texfile" }
 
-if ($map)
-  { print MAP "% This file is generated by the TeXFont Perl script.\n" ;
-    print MAP "%\n" ;
-    print MAP "% You need to add the following line to your file:\n" ;
-    print MAP "%\n" ;
-    print MAP "%   \\pdfmapfile{+$mapfile}\n" ;
-    print MAP "%\n" ;
-    print MAP "% In ConTeXt you can best use:\n" ;
-    print MAP "%\n" ;
-    print MAP "%   \\loadmapfile\[$mapfile\]\n\n" }
-
 if ($tex)
   { if ($texdata eq "")
-      { print TEX "% output=pdftex interface=en\n" ;
+      { print TEX "% interface=en\n" ;
         print TEX "\n" ;
         print TEX "\\usemodule[fnt-01]\n" ;
         print TEX "\n" ;
@@ -811,6 +848,227 @@ if ($encoding ne "") # evt -progname=context
   { $encfil = `kpsewhich -progname=pdftex $encoding$varlabel.enc` ;
     chomp $encfil ; if ($encfil eq "") { $encfil = "$encoding$varlabel.enc" } }
 
+sub build_pdftex_mapline
+  { my ($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange)  = @_;
+    my $cleanname = $fontname;
+	$cleanname =~ s/\_//gio ;
+    $option =~ s/^\s+(.*)/$1/o ;
+    $option =~ s/(.*)\s+$/$1/o ;
+    $option =~ s/  / /g ;
+    if ($option ne "")
+      { $option = "\"$option\" 4" }
+    else
+      { $option = "4" }
+    # adding cleanfont is kind of dangerous
+    my $thename = "";
+	my $str = "";
+    my $theencoding = "" ;
+    if ($strange ne "")
+      { $thename = $cleanname ; $theencoding = "" ; }
+    elsif ($lcdf)
+      { $thename = $usename ; $theencoding = " $encoding$varlabel-$cleanname.enc" }
+    elsif ($afmpl)
+      { $thename = $usename ; $theencoding = " $encoding$varlabel.enc" }
+    elsif ($virtual)
+      { $thename = $rawname ; $theencoding = " $encoding$varlabel.enc" }
+    else
+      { $thename = $usename ; $theencoding = " $encoding$varlabel.enc" }
+if ($uselmencodings) {
+    $theencoding =~ s/^(ec)\.enc/lm\-$1.enc/ ;
+}
+    # quit rest if no type 1 file
+    my $pfb_sourcepath = $sourcepath ;
+    $pfb_sourcepath =~ s@/afm/@/type1/@ ;
+    unless ((-e "$pfbpath/$fontname.$extension")||
+			(-e "$pfb_sourcepath/$fontname.$extension")||
+			(-e "$sourcepath/$fontname.$extension")||
+			(-e "$ttfpath/$fontname.$extension"))
+	  { if ($tex) { $report .= "missing file: \\type \{$fontname.pfb\}\n" }
+		report ("missing pfb file : $fontname.pfb") }
+    # now add entry to map
+    if ($strange eq "") {
+	  if ($extension eq "otf") {
+		if ($lcdf) {
+		  my $mapline = "" ;
+		  if (open(ALTMAP,"texfont.map")) {
+			while (<ALTMAP>) {
+			  chomp ;
+			  # atl: we assume this b/c we always force otftotfm --no-type1
+			  if (/<<(.*)\.otf$/oi) {
+				$mapline = $_ ; last ;
+			  }
+			}
+			close(ALTMAP) ;
+		  } else {
+			report("no mapfile from otftotfm : texfont.map") ;
+		  }
+		  if ($preproc) {
+			$mapline =~ s/<\[/</;
+			$mapline =~ s/<<(\S+)\.otf$/<$1\.pfb/ ;
+		  } else {
+			$mapline =~ s/<<(\S+)\.otf$/<< $ttfpath\/$fontname.$extension/ ;
+		  }
+		  $str = "$mapline\n" ;
+		} else {
+		  if ($preproc) {
+			$str = "$thename $cleanfont $option < $fontname.pfb$theencoding\n" ;
+		  } else {
+			# PdfTeX can't subset OTF files, so we have to include the whole thing
+			# It looks like we also need to be explicit on where to find the file
+			$str = "$thename $cleanfont $option << $ttfpath/$fontname.$extension <$theencoding\n" ;
+		  }
+		}
+	  } else {
+		$str = "$thename $cleanfont $option < $fontname.$extension$theencoding\n" ;
+	  }
+    } else {
+	  $str = "$thename $cleanfont < $fontname.$extension\n" ;
+    }
+    return ($str, $thename); }
+
+sub build_dvips_mapline
+  { my ($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange)  = @_;
+    my $cleanname = $fontname;
+	$cleanname =~ s/\_//gio ;
+    $option =~ s/^\s+(.*)/$1/o ;
+    $option =~ s/(.*)\s+$/$1/o ;
+    $option =~ s/  / /g ;
+    # adding cleanfont is kind of dangerous
+    my $thename = "";
+	my $str = "";
+    my $optionencoding = "" ;
+	my $encname = "";
+    my $theencoding = "" ;
+	if ($encoding ne "") # evt -progname=context
+	  { $encfil = `kpsewhich -progname=dvips $encoding$varlabel.enc` ;
+		chomp $encfil ;
+		if ($encfil eq "")
+         { $encfil = "$encoding$varlabel.enc" ; }
+		if (open(ENC,"<$encfil"))
+		  { while (<ENC>)
+			{ if (/^\/([^ ]+)\s*\[/)
+              { $encname = $1;
+                last; } }
+			close ENC; } }
+    if ($strange ne "")
+      { $thename = $cleanname ;
+		$optionencoding = "\"$option\""  if length($option)>1; }
+    elsif ($lcdf)
+      { $thename = $usename ;
+		$optionencoding = "\"$option $encname ReEncodeFont\" <$encoding$varlabel-$cleanname.enc" }
+    elsif ($afmpl)
+      { $thename = $usename ;
+		$optionencoding = "\"$option $encname ReEncodeFont\" <$encoding$varlabel.enc" }
+    elsif ($virtual)
+      { $thename = $rawname ;
+		$optionencoding = "\"$option $encname ReEncodeFont\" <$encoding$varlabel.enc" }
+    else
+      { $thename = $usename ;
+		$optionencoding = "\"$option $encname ReEncodeFont\" <$encoding$varlabel.enc" }
+if ($uselmencodings) {
+    $theencoding =~ s/^(ec)\.enc/lm\-$1.enc/ ;
+}
+    # quit rest if no type 1 file
+    my $pfb_sourcepath = $sourcepath ;
+    $pfb_sourcepath =~ s@/afm/@/type1/@ ;
+    unless ((-e "$pfbpath/$fontname.$extension")||
+			(-e "$pfb_sourcepath/$fontname.$extension")||
+			(-e "$sourcepath/$fontname.$extension")||
+			(-e "$ttfpath/$fontname.$extension"))
+	  { if ($tex) { $report .= "missing file: \\type \{$fontname.pfb\}\n" }
+       report ("missing pfb file : $fontname.pfb") }
+    # now add entry to map
+    if ($strange eq "") {
+	  if ($extension eq "otf") {
+		if ($lcdf) {
+		  my $mapline = "" ;
+		  if (open(ALTMAP,"texfont.map")) {
+			while (<ALTMAP>) {
+			  chomp ;
+			  # atl: we assume this b/c we always force otftotfm --no-type1
+			  if (/<<(.*)\.otf$/oi) {
+				$mapline = $_ ; last ;
+			  }
+			}
+			close(ALTMAP) ;
+		  } else {
+			report("no mapfile from otftotfm : texfont.map") ;
+		  }
+		  if ($preproc) {
+			$mapline =~ s/<\[/</;
+			$mapline =~ s/<<(\S+)\.otf$/<$1\.pfb/ ;
+		  } else {
+			$mapline =~ s/<<(\S+)\.otf$/<< $ttfpath\/$fontname.$extension/ ;
+		  }
+		  $str = "$mapline\n" ;
+		} else {
+		  if ($preproc) {
+			$str = "$thename $cleanfont $optionencoding <$fontname.pfb\n" ;
+		  } else {
+			# dvips can't subset OTF files, so we have to include the whole thing
+			# It looks like we also need to be explicit on where to find the file
+			$str = "$thename $cleanfont $optionencoding << $ttfpath/$fontname.$extension \n" ;
+		  }
+		}
+	  } else {
+		$str = "$thename $cleanfont $optionencoding <$fontname.$extension\n" ;
+	  }
+	} else {
+	  $str = "$thename $cleanfont $optionencoding <$fontname.$extension\n" ;
+	}
+    return ($str, $thename); }
+#	return $str; }
+
+
+sub build_dvipdfm_mapline
+  { my ($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange)  = @_;
+    my $cleanname = $fontname;
+	$cleanname =~ s/\_//gio ;
+	$option =~ s/([\d\.]+)\s+SlantFont/ -s $1 /;
+	$option =~ s/([\d\.]+)\s+ExtendFont/ -e $1 /;
+    $option =~ s/^\s+(.*)/$1/o ;
+    $option =~ s/(.*)\s+$/$1/o ;
+    $option =~ s/  / /g ;
+    # adding cleanfont is kind of dangerous
+    my $thename = "";
+	my $str = "";
+    my $theencoding = "" ;
+    if ($strange ne "")
+      { $thename = $cleanname ; $theencoding = "" ; }
+    elsif ($lcdf)
+      { $thename = $usename ; $theencoding = " $encoding$varlabel-$cleanname" }
+    elsif ($afmpl)
+      { $thename = $usename ; $theencoding = " $encoding$varlabel" }
+    elsif ($virtual)
+      { $thename = $rawname ; $theencoding = " $encoding$varlabel" }
+    else
+      { $thename = $usename ; $theencoding = " $encoding$varlabel" }
+if ($uselmencodings) {
+    $theencoding =~ s/^(ec)\.enc/lm\-$1.enc/ ;
+}
+    # quit rest if no type 1 file
+    my $pfb_sourcepath = $sourcepath ;
+    $pfb_sourcepath =~ s@/afm/@/type1/@ ;
+    unless ((-e "$pfbpath/$fontname.$extension")||
+			(-e "$pfb_sourcepath/$fontname.$extension")||
+			(-e "$sourcepath/$fontname.$extension")||
+			(-e "$ttfpath/$fontname.$extension"))
+	  { if ($tex) { $report .= "missing file: \\type \{$fontname.pfb\}\n" }
+		report ("missing pfb file : $fontname.pfb") }
+    # now add entry to map
+    if ($strange eq "") {
+	  if ($extension eq "otf") {
+		#TH: todo
+	  } else {
+		$str = "$thename $theencoding $fontname $option\n" ;
+	  }
+	} else {
+	  $str = "$thename $fontname $option\n" ;
+	}
+    return ($str, $thename); }
+#	return $str; }
+
+
 sub preprocess_font
   { my ($infont,$pfbfont) = @_ ;
     if ($infont ne "")
@@ -850,20 +1108,20 @@ foreach my $file (@files)
     if ($encoding ne "")
       { $encstr = " -T $encfil" }
     if ($caps ne "")
-      { $vfstr = " -V $raw$cleanname$fontsuffix" }
+      { $vfstr = " -V $use$cleanname$fontsuffix" }
     else # if ($virtual)
-      { $vfstr = " -v $raw$cleanname$fontsuffix" }
+      { $vfstr = " -v $use$cleanname$fontsuffix" }
     my $font = "";
     # let's see what we have here (we force texnansi.enc to avoid error messages)
     if ($lcdf)
       { my $command = "otfinfo -p $file" ;
-        print "$command\n" if $trace ;
+        print "$command\n" if $trace;
         $font = `$command` ;
         chomp $font ;
         $cleanname = $cleanfont = $font }
     else
       { my $command = "afm2tfm \"$file\" -p texnansi.enc texfont.tfm" ;
-        print "$command\n" if $trace ;
+        print "$command (for testing)\n" if $trace ;
         $font = `$command` ;
         UnLink "texfont.tfm" ;
         ($rawfont,$cleanfont,$restfont) = split(/\s/,$font) }
@@ -912,6 +1170,9 @@ foreach my $file (@files)
             if ($afmpl)
               { report "         generating pl : $cleanname$fontsuffix (from $cleanname)" ;
                 $encstr = " -p $encfil" ;
+if ($uselmencodings) {
+    $encstr =~ s/(ec)\.enc$/lm\-$1\.enc/ ;
+}
                 my $command = "afm2pl -f afm2tfm $shape $passon $encstr $file $cleanname$fontsuffix.vpl" ;
                 print "$command\n" if $trace ;
                 my $ok = `$command` ;
@@ -924,28 +1185,28 @@ foreach my $file (@files)
                 my $command = "afm2tfm $file $shape $passon $encstr $vfstr $raw$cleanname$fontsuffix" ;
                 print "$command\n" if $trace ;
                 $font = `$command` }
-                # generate vf file if needed
-                chomp $font ;
-                if ($font =~ /.*?([\d\.]+)\s*ExtendFont/io) { $extend = $1 }
-                if ($font =~ /.*?([\d\.]+)\s*SlantFont/io)  { $slant  = $1 }
-                if ($extend ne "") { $option .= " $1 ExtendFont " }
-                if ($slant ne "")  { $option .= " $1 SlantFont " }
-                if ($noligs) { removeligatures("$raw$cleanname$fontsuffix") }
-                if ($afmpl)
-                  { report "generating new tfm : $use$cleanname$fontsuffix" ;
-                    my $command = "pltotf $cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.tfm" ;
-                    print "$command\n" if $trace ;
-                    my $ok = `$command` }
-                elsif ($virtual)
-                  { report "generating new vf : $use$cleanname$fontsuffix (from $raw$cleanname)" ;
-                    my $command = "vptovf $raw$cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.vf $use$cleanname$fontsuffix.tfm" ;
-                    print "$command\n" if $trace ;
-                    my $ok = `$command` }
-                else
-                  { report "generating new tfm : $use$cleanname$fontsuffix (from $raw$cleanname)" ;
-                    my $command = "pltotf $raw$cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.tfm" ;
-                    print "$command\n" if $trace ;
-                    my $ok = `$command` } } }
+			# generate vf file if needed
+			chomp $font ;
+			if ($font =~ /.*?([\d\.]+)\s*ExtendFont/io) { $extend = $1 }
+			if ($font =~ /.*?([\d\.]+)\s*SlantFont/io)  { $slant  = $1 }
+			if ($extend ne "") { $option .= " $extend ExtendFont " }
+			if ($slant ne "")  { $option .= " $slant SlantFont " }
+			if ($noligs) { removeligatures("$raw$cleanname$fontsuffix") }
+			if ($afmpl)
+			  { report "generating new tfm : $use$cleanname$fontsuffix" ;
+				my $command = "pltotf $cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.tfm" ;
+				print "$command\n" if $trace ;
+				my $ok = `$command` }
+			elsif ($virtual)
+			  { report "generating new vf : $use$cleanname$fontsuffix (from $use$cleanname)" ;
+				my $command = "vptovf $use$cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.vf $use$cleanname$fontsuffix.tfm" ;
+				print "$command\n" if $trace ;
+				my $ok = `$command` }
+			else
+			  { report "generating new tfm : $use$cleanname$fontsuffix (from $raw$cleanname)" ;
+				my $command = "pltotf $raw$cleanname$fontsuffix.vpl $use$cleanname$fontsuffix.tfm" ;
+				print "$command\n" if $trace ;
+				my $ok = `$command` } } }
     elsif (-e "$sourcepath/$cleanname.tfm" )
       { report "using existing tfm : $cleanname.tfm" }
     elsif (($strange eq "expert")&&($expert))
@@ -993,85 +1254,43 @@ foreach my $file (@files)
       { UnLink ("$rawname.$suf", "$usename.$suf") ;
         UnLink ("$cleanname.$suf", "$fontname.$suf") ;
         UnLink ("$cleanname$fontsuffix.$suf", "$fontname$fontsuffix.$suf") }
-    # add line to maps file
-    $option =~ s/^\s+(.*)/$1/o ;
-    $option =~ s/(.*)\s+$/$1/o ;
-    $option =~ s/  / /o ;
-    if ($option ne "")
-      { $option = "\"$option\" 4" }
-    else
-      { $option = "4" }
-    # adding cleanfont is kind of dangerous
-    my $thename = my $str = my $theencoding = "" ;
-    if ($strange ne "")
-      { $thename = $cleanname ; $theencoding = "" ; }
-    elsif ($lcdf)
-      { $thename = $usename ; $theencoding = " $encoding$varlabel-$cleanname.enc" }
-    elsif ($afmpl)
-      { $thename = $usename ; $theencoding = " $encoding$varlabel.enc" }
-    elsif ($virtual)
-      { $thename = $rawname ; $theencoding = " $encoding$varlabel.enc" }
-    else
-      { $thename = $usename ; $theencoding = " $encoding$varlabel.enc" }
-    # quit rest if no type 1 file
-    my $pfb_sourcepath = $sourcepath ;
-    $pfb_sourcepath =~ s@/afm/@/type1/@ ;
-    unless ((-e "$pfbpath/$fontname.$extension")||
-             (-e "$pfb_sourcepath/$fontname.$extension")||
-             (-e "$sourcepath/$fontname.$extension")||
-	    (-e "$ttfpath/$fontname.$extension"))
-     { if ($tex) { $report .= "missing file: \\type \{$fontname.pfb\}\n" }
-       report ("missing pfb file : $fontname.pfb") }
-    # now add entry to map
-    if ($strange eq "") {
-        if ($extension eq "otf") {
-            if ($lcdf) {
-                my $mapline = "" ;
-                if (open(ALTMAP,"texfont.map")) {
-                    while (<ALTMAP>) {
-                        chomp ;
-                        # atl: we assume this b/c we always force otftotfm --no-type1
-                        if (/<<(.*)\.otf$/oi) {
-                            $mapline = $_ ; last ;
-                        }
-                    }
-                    close(ALTMAP) ;
-                } else {
-                    report("no mapfile from otftotfm : texfont.map") ;
-                }
-                if ($preproc) {
-                    $mapline =~ s/<\[/</;
-                    $mapline =~ s/<<(\S+)\.otf$/<$1\.pfb/ ;
-                } else {
-                    $mapline =~ s/<<(\S+)\.otf$/<< $ttfpath\/$fontname.$extension/ ;
-                }
-                $str = "$mapline\n" ;
-            } else {
-                if ($preproc) {
-                    $str = "$thename $cleanfont $option < $fontname.pfb$theencoding\n" ;
-                } else {
-                    # PdfTeX can't subset OTF files, so we have to include the whole thing
-                    # It looks like we also need to be explicit on where to find the file
-                    $str = "$thename $cleanfont $option << $ttfpath/$fontname.$extension <[$theencoding\n" ;
-                }
-            }
-        } else {
-            $str = "$thename $cleanfont $option < $fontname.$extension$theencoding\n" ;
-        }
-    } else {
-        $str = "$thename $cleanfont < $fontname.$extension\n" ;
+    # add line to map files
+	my $str = my $thename = "";
+    ($str, $thename) = build_pdftex_mapline($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange);
+	# check for redundant entries
+    if (defined $PDFTEXMAP) {
+	  $pdftexmapdata =~ s/^$thename\s.*?$//gmis ;
+	  if ($afmpl) {
+		if ($pdftexmapdata =~ s/^$rawname\s.*?$//gmis) {
+		  report ("removing raw file : $rawname") ;
+		}
+	  }
+	  $maplist .= $str ;
+	  $pdftexmapdata .= $str ;
     }
-    # check for redundant entries
-    if ($map) {
-        $mapdata =~ s/^$thename\s.*?$//gmis ;
-        if ($afmpl) {
-            if ($mapdata =~ s/^$rawname\s.*?$//gmis) {
-               report ("removing raw file : $rawname") ;
-            }
-        }
-        $maplist .= $str ;
-        $mapdata .= $str ;
+    ($str, $thename) = build_dvips_mapline($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange);
+	# check for redundant entries
+    if (defined $DVIPSMAP) {
+	  $dvipsmapdata =~ s/^$thename\s.*?$//gmis ;
+	  if ($afmpl) {
+		if ($dvipsmapdata =~ s/^$rawname\s.*?$//gmis) {
+		  report ("removing raw file : $rawname") ;
+		}
+	  }
+	  $dvipsmapdata .= $str ;
     }
+    ($str, $thename) = build_dvipdfm_mapline($option, $usename, $fontname, $rawname, $cleanfont, $encoding, $varlabel, $strange);
+	# check for redundant entries
+    if (defined $DVIPDFMMAP) {
+	  $dvipdfmmapdata =~ s/^$thename\s.*?$//gmis ;
+	  if ($afmpl) {
+		if ($dvipdfmmapdata =~ s/^$rawname\s.*?$//gmis) {
+		  report ("removing raw file : $rawname") ;
+		}
+	  }
+	  $dvipdfmmapdata .= $str ;
+    }
+
     # write lines to tex file
     if (($strange eq "expert")&&($expert)) {
         $fntlist .= "\\definefontsynonym[$cleanfont$namesuffix][$cleanname] \% expert\n" ;
@@ -1090,14 +1309,13 @@ foreach my $file (@files)
     }
 }
 
-if ($map)
-  { report ("updating map file : $mapfile") ;
-    while ($mapdata =~ s/\n\n+/\n/mois) {} ;
-    $mapdata =~ s/^\s*//gmois ;
-    print MAP $mapdata }
+finish_mapfile("pdftex",  $PDFTEXMAP,  $pdftexmapdata);
+finish_mapfile("dvipdfm", $DVIPDFMMAP, $dvipdfmmapdata);
+finish_mapfile("dvips",   $DVIPSMAP,   $dvipsmapdata);
 
 if ($tex)
-  { $mappath =~ s/\\/\//go ;
+  { my $mappath = mappath("pdftex");
+    $mappath =~ s/\\/\//go ;
     $savedoptions =~ s/^\s+//gmois ; $savedoptions =~ s/\s+$//gmois ;
     $fntlist      =~ s/^\s+//gmois ; $fntlist      =~ s/\s+$//gmois ;
     $maplist      =~ s/^\s+//gmois ; $maplist      =~ s/\s+$//gmois ;
@@ -1127,11 +1345,8 @@ if ($tex)
     print TEX "\n" ;
     print TEX "\\stoptext\n" }
 
-if ($map) { close (MAP) }
 if ($tex) { close (TEX) }
 
-copy ($mapfile,"$mappath/$mapfile") ;
-
 # atl: global cleanup with generated files (afm & ttf don't mix)
 
 UnLink(@cleanup) ;
@@ -1146,9 +1361,9 @@ print "\n" ; system ("mktexlsr $fontroot") ; print "\n" ;
 
 if ($show) { system ("texexec --once --silent $texfile") }
 
-@files = validglob("$identifier.*") ;
+@files = validglob("$identifier.* *-$identifier.map") ;
 
 foreach my $file (@files)
-  { unless ($file =~ /(tex|pdf|log|mp|tmp)$/io) { unlink $file } }
+  { unless ($file =~ /(tex|pdf|log|mp|tmp)$/io) { UnLink ($file) } }
 
 exit ;
diff --git a/scripts/context/ruby/base/ctx.rb b/scripts/context/ruby/base/ctx.rb
index 0baf5a88b..dff9570d8 100644
--- a/scripts/context/ruby/base/ctx.rb
+++ b/scripts/context/ruby/base/ctx.rb
@@ -84,7 +84,7 @@ class CtxRunner
             end
             if ! done && defaultname && FileTest.file?(defaultname) then
                 report("using default ctxfile #{defaultname}")
-                @ctxname = defaultname
+                @ctxname, done = defaultname, true
             end
             if not done then
                 report('no ctx file found')
@@ -115,23 +115,34 @@ class CtxRunner
             if @jobname then
                 variables['job'] = @jobname
             end
-            REXML::XPath.each(@xmldata.root,"//ctx:value[@name='job']") do |val|
+            root = @xmldata.root
+            begin
+                REXML::XPath.each(root,"//ctx:block") do |blk|
+                    if @jobname && blk.attributes['pattern'] then
+                        root.delete(blk) unless @jobname =~ /#{blk.attributes['pattern']}/
+                    else
+                        root.delete(blk)
+                    end
+                end
+            rescue
+            end
+            REXML::XPath.each(root,"//ctx:value[@name='job']") do |val|
                 substititute(val,variables['job'])
             end
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:message") do |mes|
+            REXML::XPath.each(root,"/ctx:job//ctx:message") do |mes|
                 report("preprocessing: #{justtext(mes)}")
             end
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:process/ctx:resources/ctx:environment") do |sty|
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:environment") do |sty|
                 @environments << justtext(sty)
             end
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:process/ctx:resources/ctx:module") do |mod|
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:module") do |mod|
                 @modules << justtext(mod)
             end
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:process/ctx:resources/ctx:filter") do |fil|
+            REXML::XPath.each(root,"/ctx:job//ctx:process/ctx:resources/ctx:filter") do |fil|
                 @filters << justtext(fil)
             end
             commands = Hash.new
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:preprocess/ctx:processors/ctx:processor") do |pre|
+            REXML::XPath.each(root,"/ctx:job//ctx:preprocess/ctx:processors/ctx:processor") do |pre|
                 begin
                     commands[pre.attributes['name']] = pre
                 rescue
@@ -139,13 +150,13 @@ class CtxRunner
             end
             suffix = @@suffix
             begin
-                suffix = REXML::XPath.match(@xmldata.root,"/ctx:job/ctx:preprocess/@suffix").to_s
+                suffix = REXML::XPath.match(root,"/ctx:job//ctx:preprocess/@suffix").to_s
             rescue
                 suffix = @@suffix
             else
                 if suffix && suffix.empty? then suffix = @@suffix end
             end
-            REXML::XPath.each(@xmldata.root,"/ctx:job/ctx:preprocess/ctx:files") do |files|
+            REXML::XPath.each(root,"/ctx:job//ctx:preprocess/ctx:files") do |files|
                 REXML::XPath.each(files,"ctx:file") do |pattern|
                     preprocessor = pattern.attributes['processor']
                     if preprocessor and not preprocessor.empty? then
@@ -267,7 +278,7 @@ class CtxRunner
                                         if f = File.open(fullname,'r') and i = REXML::Document.new(f) then
                                             report("including ctx file #{name}")
                                             REXML::XPath.each(i.root,"*") do |ii|
-                                                xmldata.root.insert_after(e,ii)
+                                                xmldata.root.insert_before(e,ii)
                                                 more = true
                                             end
                                         end
@@ -275,8 +286,8 @@ class CtxRunner
                                     end
                                 rescue
                                 end
+                                break if done
                             end
-                            break if done
                         end
                         report("no valid ctx inclusion file #{name}") unless done
                     rescue Exception
diff --git a/scripts/context/ruby/base/kpse.rb b/scripts/context/ruby/base/kpse.rb
index b0321672f..bff3cc1fa 100644
--- a/scripts/context/ruby/base/kpse.rb
+++ b/scripts/context/ruby/base/kpse.rb
@@ -28,6 +28,10 @@ class String
         end
     end
 
+    def sane_path
+        self.gsub(/\\/,'/')
+    end
+
 end
 
 class Array
@@ -36,6 +40,12 @@ class Array
         self.join(File::PATH_SEPARATOR)
     end
 
+    def non_empty
+        self.delete_if do |i|
+            (i == nil || i.empty?) rescue false
+        end
+    end
+
 end
 
 module Kpse
@@ -96,42 +106,57 @@ module Kpse
         @@scripts.keys.sort.each do |k| puts("scripts : #{k} -> #{@@scripts[k]}\n") end
     end
 
+    def Kpse.used_path(varname)
+        begin
+            if @@mswindows then
+                path = run("--expand-path=\$#{varname}") rescue ''
+            else
+                path = run("--expand-path='$#{varname}'") rescue ''
+            end
+        rescue
+            path = ''
+        end
+        return path.sane_path
+    end
+
     def Kpse.found(filename, progname=nil, format=nil)
         begin
             tag = Kpse.key(filename) # all
             if @@located.key?(tag) then
-                return @@located[tag]
+                return @@located[tag].sane_path
             elsif FileTest.file?(filename) then
                 setvariable(tag,filename)
                 return filename
             elsif FileTest.file?(File.join(@@ownpath,filename)) then
                 setvariable(tag,File.join(@@ownpath,filename))
-                return @@located[tag]
+                return @@located[tag].sane_path
             else
                 [progname,@@progname].flatten.compact.uniq.each do |prg|
                     [format,@@formats].flatten.compact.uniq.each do |fmt|
                         begin
                             tag = Kpse.key(filename,prg,fmt)
                             if @@located.key?(tag) then
-                                return @@located[tag]
+                                return @@located[tag].sane_path
                             elsif p = Kpse.kpsewhich(filename,prg,fmt) then
                                 setvariable(tag,p.chomp)
-                                return @@located[tag]
+                                return @@located[tag].sane_path
                             end
                         rescue
                         end
                     end
                 end
                 setvariable(tag,filename)
-                return filename
+                return filename.sane_path
             end
         rescue
-            filename
+            filename.sane_path
         end
     end
 
     def Kpse.kpsewhich(filename,progname,format)
-        Kpse.run("-progname=#{progname} -format=\"#{format}\" #{filename}")
+        p = if progname && ! progname.empty? then "-progname=#{progname}" else '' end
+        f = if format   && ! format.empty?   then "-format=\"#{format}\"" else '' end
+        Kpse.run("#{p} #{f} #{filename}")
     end
 
     def Kpse.which
@@ -160,7 +185,7 @@ module Kpse
         # maybe we should check for writeability
         unless @@paths.key?('formatpaths') then
             begin
-                setpath('formatpaths',run("--show-path=fmt").gsub(/\\/,'/').split_path)
+                setpath('formatpaths',run("--show-path=fmt").sane_path.split_path)
             rescue
                 setpath('formatpaths',[])
             end
diff --git a/scripts/context/ruby/base/kpsefast.rb b/scripts/context/ruby/base/kpsefast.rb
index 20c07c70a..24ff1a0fa 100644
--- a/scripts/context/ruby/base/kpsefast.rb
+++ b/scripts/context/ruby/base/kpsefast.rb
@@ -9,6 +9,8 @@
 # www       : www.pragma-ade.com
 
 # todo: multiple cnf files
+#
+# todo: cleanup, string or table store (as in lua variant)
 
 class String
 
diff --git a/scripts/context/ruby/base/mp.rb b/scripts/context/ruby/base/mp.rb
index b30be1110..5dd2948cf 100644
--- a/scripts/context/ruby/base/mp.rb
+++ b/scripts/context/ruby/base/mp.rb
@@ -91,8 +91,8 @@ EOT
                     f.puts("")
                     f.puts(@@start[method])
                 end
-                data.gsub!(/[^\\]%.*?$/mo) do
-                    ''
+                data.gsub!(/([^\\])%.*?$/mo) do
+                    $1
                 end
                 data.scan(/(verbatim|b)tex\s*(.*?)\s*etex/mo) do
                     tag, text = $1, $2
diff --git a/scripts/context/ruby/base/tex.rb b/scripts/context/ruby/base/tex.rb
index a6403dcde..f6f3dc4ed 100644
--- a/scripts/context/ruby/base/tex.rb
+++ b/scripts/context/ruby/base/tex.rb
@@ -85,6 +85,9 @@ class TEX
 
     @@pdftex     = 'pdftex' # new default, pdfetex is gone
 
+    @@luafiles  = "luafiles.tmp"
+    @@luatarget = "lua/context"
+
     ENV['PATH'].split(File::PATH_SEPARATOR).each do |p|
         if System.unix? then
             pp, pe = "#{p}/pdftex"    , "#{p}/pdfetex"
@@ -113,7 +116,7 @@ class TEX
     ['pdfetex','pdftex','pdf','pdftex','standard'] .each do |b| @@backends[b]   = 'pdftex'    end
     ['dvipdfmx','dvipdfm','dpx','dpm']             .each do |b| @@backends[b]   = 'dvipdfmx'  end
     ['xetex','xtx']                                .each do |b| @@backends[b]   = 'xetex'     end
-    ['dvips','ps']                                 .each do |b| @@backends[b]   = 'dvips'     end
+    ['dvips','ps','dvi']                           .each do |b| @@backends[b]   = 'dvips'     end
     ['dvipsone']                                   .each do |b| @@backends[b]   = 'dvipsone'  end
     ['acrobat','adobe','distiller']                .each do |b| @@backends[b]   = 'acrobat'   end
     ['xdv','xdv2pdf']                              .each do |b| @@backends[b]   = 'xdv2pdf'   end
@@ -164,7 +167,7 @@ class TEX
     @@runoptions['xetex']   = ['--8bit  -no-pdf'] # from now on we assume (x)dvipdfmx to be used
     @@runoptions['pdfetex'] = ['--8bit ']
     @@runoptions['pdftex']  = ['--8bit ']         # pdftex is now pdfetex
-    @@runoptions['luatex']  = ['--8bit ']
+    @@runoptions['luatex']  = ['']
     @@runoptions['aleph']   = ['--8bit ']
 
     @@booleanvars = [
@@ -225,6 +228,29 @@ class TEX
         @@extrabooleanvars << vars
     end
 
+    # def jobvariables(names=nil)
+        # if [names ||[]].flatten.size == 0 then
+            # names = [allbooleanvars,allstringvars].flatten
+        # end
+        # data = Hash.new
+        # names.each do |name|
+            # if allbooleanvars.include?(name) then
+                # data[name] = if getvariable(name) then "yes" else "no" end
+            # else
+                # data[name] = getvariable(name)
+            # end
+        # end
+        # data
+    # end
+
+    # def setjobvariables(names=nil)
+        # assignments = Array.new
+        # jobvariables(names).each do |k,v|
+            # assignments << "#{k}=\{#{v}\}"
+        # end
+        # "\setvariables[exe][#{assignments.join(", ")}]"
+    # end
+
     @@temprunfile = 'texexec'
     @@temptexfile = 'texexec.tex'
 
@@ -524,6 +550,41 @@ class TEX
         return version
     end
 
+    def cleanupluafiles
+        File.delete(@@luafiles) rescue false
+    end
+
+    def compileluafiles
+        begin
+            Dir.glob("lua/context/*.luc").each do |luc|
+                File.delete(luc) rescue false
+            end
+        rescue
+        end
+        if data = (IO.readlines(@@luafiles) rescue nil) then
+            report("compiling lua files (using #{File.expand_path(@@luafiles)})")
+            begin
+                Dir.makedirs(@@luatarget) rescue false
+                data.each do |line|
+                    luafile = line.chomp
+                    lucfile = File.basename(luafile).gsub(/\..*?$/,'') + ".luc"
+                    if runcommand(["luac","-s","-o",quoted(File.join(Dir.getwd,@@luatarget,lucfile)),quoted(luafile)]) then
+                        report("#{File.basename(luafile)} converted to #{File.basename(lucfile)}")
+                    else
+                        report("#{File.basename(luafile)} not converted to #{File.basename(lucfile)}")
+                    end
+                end
+            rescue
+                report("fatal error in compilation")
+            end
+        else
+            report("no lua compilations needed")
+        end
+        File.delete(@@luafiles) rescue false
+    end
+
+    # we need engine methods
+
     def makeformats
 
         checktestversion
@@ -561,9 +622,18 @@ class TEX
                     makeuserfile
                     makeresponsefile
                 end
-                texformats.each do |texformat|
-                    report("generating tex format #{texformat}")
-                    runcommand([quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine),texmakeextras(texformat)])
+                if texengine == 'luatex' then
+                    cleanupluafiles
+                    texformats.each do |texformat|
+                        report("generating tex format #{texformat}")
+run_luatools("--ini --compile #{texformat}")
+                    end
+                    compileluafiles
+                else
+                    texformats.each do |texformat|
+                        report("generating tex format #{texformat}")
+                        runcommand([quoted(texengine),prognameflag(progname),iniflag,tcxflag,prefixed(texformat,texengine),texmakeextras(texformat)])
+                    end
                 end
             else
                 report("unable to make format due to lack of permissions")
@@ -592,8 +662,10 @@ class TEX
             mpsformatpath = ''
         end
         # check for problems
+        report("")
         report("tex engine path: #{texformatpath}") unless texformatpath.empty?
         report("mps engine path: #{mpsformatpath}") unless mpsformatpath.empty?
+        report("")
         [['fmt','tex'],['mem','mps']].each do |f|
             [[texformatpath,'global'],[mpsformatpath,'global'],[savedpath,'current']].each do |p|
                 begin
@@ -601,11 +673,20 @@ class TEX
                 rescue
                 else
                     Dir.glob("*.#{f[0]}").each do |file|
-                        report("#{f[1]}format: #{filestate(file)} > #{File.expand_path(file)}")
+                        report("#{f[1]}: #{filestate(file)} > #{File.expand_path(file)} (#{File.size(file)})")
                     end
                 end
             end
         end
+        begin
+            lucdir = File.join(texformatpath,@@luatarget)
+            Dir.chdir(lucdir)
+        rescue
+        else
+            Dir.glob("*.luc").each do |file|
+                report("luc: #{filestate(file)} > #{File.expand_path(file)} (#{File.size(file)})")
+            end
+        end
         # to be sure, go back to current path
         begin
             Dir.chdir(savedpath)
@@ -613,6 +694,7 @@ class TEX
         end
         # finalize
         cleanup
+        report("")
         reportruntime
     end
 
@@ -853,10 +935,10 @@ class TEX
         rname = File.unsuffixed(resultname)
         if ! rname.empty? && (rname != fname) then
             report("outputfile #{rname}")
-            ['tuo','log','dvi','pdf'].each do |s|
+            ['tuo','tuc','log','dvi','pdf'].each do |s|
                 File.silentrename(File.suffixed(fname,s),File.suffixed('texexec',s))
             end
-            ['tuo'].each do |s|
+            ['tuo','tuc'].each do |s|
                 File.silentrename(File.suffixed(rname,s),File.suffixed(fname,s)) if FileTest.file?(File.suffixed(rname,s))
             end
         end
@@ -867,12 +949,12 @@ class TEX
         rname = File.unsuffixed(resultname)
         if ! rname.empty? && (rname != fname) then
             report("renaming #{fname} to #{rname}")
-            ['tuo','log','dvi','pdf'].each do |s|
+            ['tuo','tuc','log','dvi','pdf'].each do |s|
                 File.silentrename(File.suffixed(fname,s),File.suffixed(rname,s))
             end
             report("restoring #{fname}")
             unless $fname == 'texexec' then
-                ['tuo','log','dvi','pdf'].each do |s|
+                ['tuo','tuc','log','dvi','pdf'].each do |s|
                     File.silentrename(File.suffixed('texexec',s),File.suffixed(fname,s))
                 end
             end
@@ -1034,6 +1116,20 @@ class TEX
 
     public
 
+    def run_luatools(args)
+        # dirty trick: we know that the lua path is relative to the ruby path; of course this
+        # will not work well when stubs are used
+        [(ENV["_CTX_K_S_texexec_"] or ENV["_CTX_K_S_THREAD_"] or ENV["TEXMFSTART.THREAD"]), File.dirname($0)].each do |path|
+            if path then
+                script = "#{path}/../lua/luatools.lua"
+                if FileTest.file?(script) then
+                    return runcommand("lua #{script} #{args}")
+                end
+            end
+        end
+        return runcommand("texmfstart luatools #{args}")
+    end
+
     def processmpgraphic
         getarrayvariable('files').each do |filename|
             setvariable('filename',filename)
@@ -1126,6 +1222,38 @@ class TEX
         reportruntime
     end
 
+    def processmpstatic
+        if filename = getvariable('filename') then
+            filename += ".mp" unless filename =~ /\..+?$/
+            if FileTest.file?(filename) then
+                begin
+                    data = IO.read(filename)
+                    File.open("texexec.tex",'w') do |f|
+                        f << "\\setupoutput[pdftex]\n"
+                        f << "\\setupcolors[state=start]\n"
+                        data.sub!(/^%mpenvironment\:\s*(.*?)$/mois) do
+                            f << $1
+                            "\n"
+                        end
+                        f << "\\starttext\n"
+                        f << "\\startMPpage\n"
+                        f << data.gsub(/end\.*\s*$/m, '') # a bit of a hack
+                        f << "\\stopMPpage\n"
+                        f << "\\stoptext\n"
+                    end
+                    report("converting static '#{filename}'")
+                    runtex("texexec.tex")
+                    pdffile = File.suffixed(filename,'pdf')
+                    File.silentrename("texexec.pdf",pdffile)
+                    report ("#{filename} converted to #{pdffile}")
+                rescue
+                    report("error in converting #{filename} (#{$!}")
+                end
+            end
+        end
+        reportruntime
+    end
+
     def processmpxtex
         getarrayvariable('files').each do |filename|
             setvariable('filename',filename)
@@ -1372,7 +1500,11 @@ class TEX
         report("progname: #{progname}")
         if texengine && texformat && progname then
             fixbackendvars(@@mappaths[texengine])
+if texengine == "luatex" then
+    run_luatools("--fmt=#{texformat} #{filename}")
+else
             runcommand([quoted(texengine),prognameflag(progname),formatflag(texengine,texformat),tcxflag,runoptions(texengine),filename,texprocextras(texformat)])
+end
             # true
         else
             false
@@ -1451,7 +1583,25 @@ class TEX
         end
     end
 
-    # 1=tex 2=mptex 3=mpxtex 4=mpgraphic
+    def runluacheck(jobname)
+        if false then
+            # test-pos.tex / 6 meg tua file: 18.6 runtime
+            old, new = File.suffixed(jobname,'tua'), File.suffixed(jobname,'tuc')
+            if FileTest.file?(old) then
+                report("converting #{old} into #{new}")
+                system("luac -s -o #{new} #{old}")
+            end
+        else
+            # test-pos.tex / 6 meg tua file: 17.5 runtime
+            old, new = File.suffixed(jobname,'tua'), File.suffixed(jobname,'tuc')
+            if FileTest.file?(old) then
+                report("renaming #{old} into #{new}")
+                File.rename(old,new) rescue false
+            end
+        end
+    end
+
+    # 1=tex 2=mptex 3=mpxtex 4=mpgraphic 5=mpstatic
 
     def runtexexec(filename=[], options=[], mode=nil)
         begin
@@ -1470,6 +1620,7 @@ class TEX
                     when 2 then job.processmptex
                     when 3 then job.processmpxtex
                     when 4 then job.processmpgraphic
+                    when 5 then job.processmpstatic
                 end
                 job.inspect && Kpse.inspect if getvariable('verbose')
                 return true
@@ -1658,6 +1809,7 @@ class TEX
                         ok = runtex(if dummyfile || forcexml then rawbase else rawname end)
                         if ok then
                             ok = runtexutil(rawbase) if getvariable('texutil') || getvariable('forcetexutil')
+                            runluacheck(rawbase)
                             runbackend(rawbase)
                             popresult(rawbase,result)
                         end
@@ -1667,10 +1819,11 @@ class TEX
                             end
                         end
                     else
+# goto tmp/jobname when present
                         mprundone, ok, stoprunning = false, true, false
                         texruns, nofruns = 0, getvariable('runs').to_i
                         state = FileState.new
-                        ['tub','tuo'].each do |s|
+                        ['tub','tuo','tuc'].each do |s|
                             state.register(File.suffixed(rawbase,s))
                         end
                         if getvariable('automprun') then # check this
@@ -1690,13 +1843,16 @@ class TEX
                                     makeoptionfile(rawbase,jobname,orisuffix,false,false,2,texruns) # unknown
                                 end
                             end
+# goto .
                             ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
+# goto tmp/jobname when present
                             if ok && (nofruns > 1) then
                                 unless getvariable('nompmode') then
                                     mprundone = runtexmpjob(rawbase, "mpgraph")
                                     mprundone = runtexmpjob(rawbase, "mprun")
                                 end
                                 ok = runtexutil(rawbase)
+                                runluacheck(rawbase)
                                 state.update
                                 stoprunning = state.stable?
                             end
@@ -1704,11 +1860,16 @@ class TEX
                         if not ok then
                             setvariable('error','error in tex file')
                         end
-                        ok = runtexutil(rawbase) if (nofruns == 1) && getvariable('texutil')
+                        if (nofruns == 1) && getvariable('texutil') then
+                            ok = runtexutil(rawbase)
+                            runluacheck(rawbase)
+                        end
                         if ok && finalrun && (nofruns > 1) then
                             makeoptionfile(rawbase,jobname,orisuffix,true,finalrun,4,texruns) unless getvariable('nooptionfile')
                             report("final TeX run #{texruns}")
+# goto .
                             ok = runtex(File.suffixed(if dummyfile || forcexml then rawbase else rawname end,jobsuffix))
+# goto tmp/jobname when present
                         end
                         if getvariable('keep') then
                             ['top','log','run'].each do |suffix|
@@ -1721,8 +1882,11 @@ class TEX
                              # File.silentdelete(File.suffixed(rawbase,s))
                         # end
                         if ok then
+# goto .
                             runbackend(rawbase)
                             popresult(rawbase,result)
+# goto tmp/jobname when present
+# skip next
                         end
                         if true then # autopurge
                             begin
@@ -1755,14 +1919,14 @@ class TEX
                                     end
                                 end
                             rescue
-                                report("fatal error #{$!}")
+                                # report("fatal error #{$!}")
                             end
                         end
                     end
 
                     Kpse.runscript('ctxtools',rawbase,'--purge')       if getvariable('purge')
                     Kpse.runscript('ctxtools',rawbase,'--purge --all') if getvariable('purgeall')
-
+# till here
                 when 'latex' then
 
                     ok = runtex(rawname)
@@ -1913,7 +2077,7 @@ class TEX
 
     def purge_mpx_files(mpname)
         unless getvariable('keep') then
-            ['tex', 'log', 'tui', 'tuo', 'top'].each do |suffix|
+            ['tex', 'log', 'tui', 'tuo', 'tuc', 'top'].each do |suffix|
                 File.silentdelete(File.suffixed(mpname,'temp',suffix))
             end
         end
diff --git a/scripts/context/ruby/base/texutil.rb b/scripts/context/ruby/base/texutil.rb
index 2bca83167..7c402b98f 100644
--- a/scripts/context/ruby/base/texutil.rb
+++ b/scripts/context/ruby/base/texutil.rb
@@ -235,7 +235,11 @@ class TeXUtil
         end
 
         def tokenize(str)
-            str.gsub(/\\strchr\{(.*?)\}/o) do "\\#{$1}" end
+            if str then
+                str.gsub(/\\strchr\{(.*?)\}/o) do "\\#{$1}" end
+            else
+                ""
+            end
         end
 
         def remap(str)
@@ -461,7 +465,6 @@ class TeXUtil
             class Synonym
 
                 @@debug = false
-                @@debug = true
 
                 def initialize(t, c, k, d)
                     @type, @command, @key, @sortkey, @data = t, c, k, k, d
@@ -559,7 +562,6 @@ class TeXUtil
                 @@specialbanner = "" # \\relax"
 
                 @@debug = false
-                @@debug = true
 
                 @@howto = /^(.*?)\:\:(.*)$/o
                 @@split = ' && '
@@ -598,7 +600,8 @@ class TeXUtil
                             # end
                         end
                     else
-                        @entry, @key = cleanupsplit(@entry), cleanupsplit(@key)
+                        # @entry, @key = cleanupsplit(@entry), cleanupsplit(@key)
+@entry, @key = cleanupsplit(@entry), xcleanupsplit(@key)
                     end
                     @sortkey = sorter.simplify(@key)
                     # special = @sortkey =~ /^([^a-zA-Z\\])/o
@@ -613,7 +616,7 @@ class TeXUtil
                         @entry,
                         @texthowto.ljust(10,' '),
                         # @state, # no, messes up things
-                        (@realpage ||'').rjust(6,' ').gsub(/0/,' '),
+                        (@realpage.to_s || '').rjust(6,' ').gsub(/0/,' '),
                         # (@realpage ||'').rjust(6,' '),
                         @pagehowto
                     ].join(@@split)
@@ -628,6 +631,23 @@ class TeXUtil
                     end
                 end
 
+def xcleanupsplit(target) # +a+b+c &a&b&c a+b+c a&b&c
+    t = Array.new
+    case target[0,1]
+        when '&' then
+            t = target.sub(/^./o,'').split(/([^\\])\&/o)
+        when '+' then
+            t = target.sub(/^./o,'').split(/([^\\])\+/o)
+        else
+            # t = target.split(/([^\\])[\&\+]/o)
+            # t = target.split(/[\&\+]/o)
+            t = target.split(/(?!\\)[\&\+]/o) # lookahead
+    end
+    if not t[1] then t[1] = " " end # we need some entry else we get subentries first
+    if not t[2] then t[2] = " " end # we need some entry else we get subentries first
+    return t.join(@@split)
+end
+
                 def <=> (other)
                     @sortkey <=> other.sortkey
                 end
@@ -659,11 +679,13 @@ class TeXUtil
                         alphaclass, alpha = '', ''
                         @@savedhowto, @@savedfrom, @@savedto, @@savedentry = '', '', '', ''
                         if @@debug then
+                        # if true then
                             list.each do |entry|
                                 handle << "% [#{entry.sortkey.gsub(/#{@@split}/o,'] [')}]\n"
                             end
                         end
                         list.each do |entry|
+# puts(entry.sortkey.gsub(/\s+/,""))
                             if entry.sortkey =~ /^(\S+)/o then
                                 if sorter.division?($1) then
                                     testalpha = sorter.getdivision($1)
@@ -738,6 +760,7 @@ class TeXUtil
                             elsif @@savedhowto != entry.pagehowto and ! entry.pagehowto.empty? then
                                 @@savedhowto = entry.pagehowto
                             end
+                            # beware, we keep multiple page entries per realpage because of possible prefix usage
                             if copied || ! ((lastpage == entry.page) && (lastrealpage == entry.realpage)) then
                                 nextentry = "{#{entry.type}}{#{previous[0]}}{#{previous[1]}}{#{previous[2]}}{#{entry.pagehowto},#{entry.texthowto}}"
                                 savedline = "{#{entry.type}}{#{@@savedhowto},#{entry.texthowto}}{#{entry.location}}{#{entry.page}}{#{entry.realpage}}"
@@ -791,7 +814,8 @@ class TeXUtil
                         @@registers[data[1]].push(Register.new(3,data[1],data[2],data[3],data[4],nil,data[5],data[6]))
                     when 's' then
                         @@registers[data[1]] = Array.new unless @@registers.key?(data[1])
-                        @@registers[data[1]].push(Register.new(4,data[1],data[2],data[3],data[4],data[5],data[6],nil))
+                        # was this but wrong sort order       (4,data[1],data[2],data[3],data[4],data[5],data[6],nil))
+                        @@registers[data[1]].push(Register.new(4,data[1],data[2],data[3],data[4],data[5],data[6],0))
                     when 'l' then
                         @@languages[data[1]] = data[2] || ''
                 end
@@ -820,6 +844,7 @@ class TeXUtil
                     @@registers[s].each_index do |i|
                         @@registers[s][i].build(@@sorter[s])
                     end
+                    # @@registers[s].uniq!
                     @@registers[s] = @@registers[s].sort
                 end
             end
diff --git a/scripts/context/ruby/concheck.rb b/scripts/context/ruby/concheck.rb
index bf09bbdc8..6c7512bff 100644
--- a/scripts/context/ruby/concheck.rb
+++ b/scripts/context/ruby/concheck.rb
@@ -223,6 +223,7 @@ def some_chr_error(data, filename, left, right)
     levels = Array.new
     for line in 0..data.length-1 do
          str = data[line]
+         # str = data[line].gsub(/\\[\#{left}\#{right}]/,'')
          column = 0
          while column<str.length do
             case str[column].chr
@@ -365,6 +366,7 @@ end
 # todo : language dependent
 
 def check_file_tex (filename)
+    error = false
     if data = load_file(filename) then
         message("checking tex file", filename)
         interface = guess_interface(data)
@@ -372,42 +374,49 @@ def check_file_tex (filename)
         data = cleanup_data(data,interface)
         # data.each do |d| print d  end
         $valid[interface].each do |v|
-            return false if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex)
+            if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex) then
+                error = true
+                break
+            end
         end
         # return false if some_wrd_error(data, filename, '\\\\start'   , '\\\\stop'   , $valid_tex)
         # return false if some_wrd_error(data, filename, '\\\\Start'   , '\\\\Stop'   , $valid_tex)
         # return false if some_wrd_error(data, filename, '\\\\beginvan', '\\\\eindvan', $valid_tex)
         # return false if some_wrd_error(data, filename, '\\\\begin'   , '\\\\end|\\\\eind', $valid_tex)
-        return false if some_sym_error(data, filename, '$', false)
-        return false if some_sym_error(data, filename, '|', true)
-        return false if some_chr_error(data, filename, '{', '}')
-        return false if some_chr_error(data, filename, '[', ']')
-        return false if some_chr_error(data, filename, '(', ')')
-        return false if some_key_error(data, filename, valid)
-        message("no errors in tex code", filename)
-        return true
+        error = true if some_sym_error(data, filename, '$', false)
+        error = true if some_sym_error(data, filename, '|', true)
+        error = true if some_chr_error(data, filename, '{', '}')
+        error = true if some_chr_error(data, filename, '[', ']')
+        error = true if some_chr_error(data, filename, '(', ')')
+        error = true if some_key_error(data, filename, valid)
+        message("no errors in tex code", filename) unless error
+        return error
     else
         return false
     end
 end
 
 def check_file_mp (filename)
+    error = false
     if data = load_file(filename) then
         message("checking metapost file", filename)
         interface = guess_interface(data)
         valid = load_valid(data,interface)
         $valid[interface].each do |v|
-            return false if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex)
+            if some_wrd_error(data, filename, v[0], v[1] ,$valid_tex) then
+                error = true
+                break
+            end
         end
         # return false if some_wrd_error(data, filename, '', 'begin', 'end', $valid_mp)
-        return false if some_chr_error(data, filename, '{', '}')
-        return false if some_chr_error(data, filename, '[', ']')
-        return false if some_chr_error(data, filename, '(', ')')
-        return false if some_key_error(data, filename, valid)
-        message("no errors in metapost code", filename)
-        return true
+        error = true if some_chr_error(data, filename, '{', '}')
+        error = true if some_chr_error(data, filename, '[', ']')
+        error = true if some_chr_error(data, filename, '(', ')')
+        error = true if some_key_error(data, filename, valid)
+        message("no errors in metapost code", filename) unless error
+        return error
     else
-        return true
+        return false
     end
 end
 
@@ -440,7 +449,7 @@ def check_file(filename='')
         when '' then
             message("provide filename")
             return false
-        when /\.tex$/i then
+        when /\.(tex|mk.+)$/i then
             return check_file_tex(filename) # && check_file_text(filename)
         when /\.mp$/i then
             return check_file_mp(filename)
@@ -450,12 +459,13 @@ def check_file(filename='')
     end
 end
 
-if filename = ARGV[0] then
-    if check_file(filename) then
-        exit 0
-    else
-        exit 1
+if ARGV.size > 0 then
+    someerror = false
+    ARGV.each do |filename|
+         somerror = true if check_file(filename)
     end
+    exit (if someerror then 1 else 0 end)
 else
     exit 1
 end
+
diff --git a/scripts/context/ruby/ctxtools.rb b/scripts/context/ruby/ctxtools.rb
index 0cf96e10d..567c927a5 100644
--- a/scripts/context/ruby/ctxtools.rb
+++ b/scripts/context/ruby/ctxtools.rb
@@ -46,16 +46,13 @@
 
 banner = ['CtxTools', 'version 1.3.3', '2004/2006', 'PRAGMA ADE/POD']
 
-# todo dirname
-
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
 require 'base/system'
+require 'base/kpse'
+require 'base/file'
 
 require 'rexml/document'
 require 'net/http'
@@ -86,6 +83,10 @@ class String
         end
     end
 
+    def nosuffix(suffix)
+        self.sub(/\.#{suffix}/,'') # no /o
+    end
+
 end
 
 class Commands
@@ -108,7 +109,7 @@ class Commands
         maincontextfile = 'context.tex'
         unless FileTest.file?(maincontextfile) then
             begin
-                maincontextfile = `kpsewhich -progname=context #{maincontextfile}`.chomp
+                maincontextfile = Kpse.found(maincontextfile,'context')
             rescue
                 maincontextfile = ''
             end
@@ -417,6 +418,8 @@ class Commands
 
     public
 
+    # faster is to glob the whole dir and regexp over that list
+
     def purgefiles
 
         pattern  = @commandline.arguments
@@ -444,13 +447,16 @@ class Commands
             files = Dir.glob(globbed)
             report("purging#{if purgeall then ' all' end} temporary files : #{globbed}")
         else
+            report("purging#{if purgeall then ' all' end} temporary files : #{pattern.join(' ')}")
             pattern.each do |pat|
-                globbed = if recurse then "**/#{pat}-*.*" else "#{pat}-*.*" end
+                nosuf = File.unsuffixed(pat)
+                globbed = if recurse then "**/#{nosuf}-*.*" else "#{nosuf}-*.*" end
+                report("checking files that match '#{globbed}'")
                 files = Dir.glob(globbed)
-                globbed = if recurse then "**/#{pat}.*" else "#{pat}.*" end
+                globbed = if recurse then "**/#{nosuf}.*" else "#{nosuf}.*" end
+                report("checking files that match '#{globbed}'")
                 files.push(Dir.glob(globbed))
             end
-            report("purging#{if purgeall then ' all' end} temporary files : #{pattern.join(' ')}")
         end
         files.flatten!
         files.sort!
@@ -522,6 +528,7 @@ class Commands
     $dontaskprefixes = [
         # "tex-form.tex", "tex-edit.tex", "tex-temp.tex",
         "texexec.tex", "texexec.tui", "texexec.tuo",
+        "texexec.tuc", "texexec.tua",
         "texexec.ps", "texexec.pdf", "texexec.dvi",
         "cont-opt.tex", "cont-opt.bak"
     ]
@@ -531,7 +538,7 @@ class Commands
         "xlscript\\.xsl"
     ]
     $forsuresuffixes = [
-        "tui", "tup", "ted", "tes", "top",
+        "tui", "tua", "tup", "ted", "tes", "top",
         "log", "tmp", "run", "bck", "rlg",
         "mpt", "mpx", "mpd", "mpo", "mpb",
         "ctl",
@@ -541,7 +548,7 @@ class Commands
         "dvi", "ps", "pdf"
     ]
     $texnonesuffixes = [
-        "tuo", "tub", "top"
+        "tuo", "tub", "top", "tuc"
     ]
     $dummyfiles = [
         "mpgraph"
@@ -639,7 +646,7 @@ class Commands
                 nofdocuments, nofdefinitions, nofskips = 0, 0, 0
                 skiplevel, indocument, indefinition, skippingbang = 0, false, false, false
                 if processtype.empty? then
-                  filetype = filesuffix.downcase
+                  filetype = filesuffix.downcase.sub(/^mk.+$/,'tex') # make sure that mkii and mkiv files are handled
                 else
                   filetype = processtype.downcase
                 end
@@ -1049,7 +1056,7 @@ class Language
         commentfile = rmename.dup
 
         begin
-            desfile = `kpsewhich -progname=context #{desname}`.chomp
+            desfile = Kpse.found(desname,'context')
             if f = File.new(desfile) then
                 if doc = REXML::Document.new(f) then
                     if e = REXML::XPath.first(doc.root,"/descriptions/description[@language='#{@language}']") then
@@ -1188,7 +1195,7 @@ class Language
 
     def located(filename)
         begin
-            fname = `kpsewhich -progname=context #{filename}`.chomp
+            fname = Kpse.found(filename, 'context')
             if FileTest.file?(fname) then
                 report("using file #{fname}")
                 return fname
@@ -1519,7 +1526,7 @@ class Language
 
         if ! encoding.empty? then
             begin
-                filename = `kpsewhich -progname=context #{filename}`
+                filename = Kpse.found(filename, 'context')
                 if data = IO.readlines(filename.chomp) then
                     report("preloading #{encoding} character mappings")
                     accept = false
@@ -1865,8 +1872,7 @@ class Commands
         entities   = Hash.new
 
         filenames.each do |filename|
-          # filename = `texmfstart tmftools.rb --progname=context #{filename}`.chomp
-            filename = `kpsewhich --progname=context #{filename}`.chomp
+            filename = Kpse.found(filename, 'context')
             if filename and not filename.empty? and FileTest.file?(filename) then
                 report("loading #{filename.gsub(/\\/,'/')}") unless outputname.empty?
                 IO.readlines(filename).each do |line|
@@ -1874,7 +1880,7 @@ class Commands
                         when /^[\#\%]/io then
                             # skip comment line
                         when /\\definecharacter\s+([a-z]+)\s+\{\\uchar\{*(\d+)\}*\{(\d+)\}\}/io then
-                            name, code = $1, ($2.to_i*256 + $3.to_i).to_s
+                            name, code = $1, sprintf("%04X",$2.to_i*256 + $3.to_i)
                             entities[name] = code.rjust(4,'0') unless entities.key?(name)
                         when /^([A-F0-9]+)\;([a-z][a-z]+)\;(.*?)\;(.*?)\s*$/io then
                             code, name, adobe, comment = $1, $2, $3, $4
@@ -2076,187 +2082,424 @@ class TexDeps
         noInputMode noOutputMode noDefaultInputMode noDefaultOutputMode
     /.split
 
-    @@cs_plain = %q/
-        TeX
-        bgroup egroup endgraf space empty null
-        newcount newdimen newskip newmuskip newbox newtoks newhelp newread newwrite newfam newlanguage newinsert newif
-        maxdimen magstephalf magstep
-        frenchspacing nonfrenchspacing normalbaselines obeylines obeyspaces raggedright ttraggedright
-        thinspace negthinspace enspace enskip quad qquad
-        smallskip medskip bigskip removelastskip topglue vglue hglue
-        break nobreak allowbreak filbreak goodbreak smallbreak medbreak bigbreak
-        line leftline rightline centerline rlap llap underbar strutbox strut
-        cases matrix pmatrix bordermatrix eqalign displaylines eqalignno leqalignno
-        pageno folio tracingall showhyphens fmtname fmtversion
-        hphantom vphantom phantom smash
+    @@cs_metatex = %q/
     /.split
 
-    @@cs_eplain = %q/
-        eTeX
-        newmarks grouptype interactionmode nodetype iftype
-        tracingall loggingall tracingnone
+    @@cs_xetex = %q/
+    /.split
+
+    @@cs_skip = %q/
+        v\! c\! s\! e\! m\! f\!
+        \!tf \!tt \!tq \!ta \?\?
+        csname endcsname relax
+        \!\!string[a-f] \!\!dimen[a-k] \!\!count[a-f] \!\!toks[a-e] \!\!box[a-e]
+        \!\!width[a-c] \!\!height[a-c] \!\!depth[a-c]
+        \!\!done[a-f] if\!\!done[a-f] if\:\!\!done[a-f]
+        scratch globalscratch
+        ascii[a-d] globalascii
+        @@expanded @@globalexpanded @EA @EAEA @EAEAEA
+        bgroup egroup par next nextnext docommand dodocommand dododocommand
+        \!\!width \!\!height \!\!depth \!\!plus \!\!minus \!\!to
+    /.split
+
+    @@cs_skip = %q/
+        [vcsemf]\! \?\?
+        \!t[ftqa]
+        csname endcsname relax
+        \!\!string[a-f] \!\!dimen[a-k] \!\!count[a-f] \!\!toks[a-e] \!\!box[a-e]
+        \!\!width[a-c] \!\!height[a-c] \!\!depth[a-c]
+        \!\!done[a-f] if\!\!done[a-f] if\:\!\!done[a-f]
+        scratch globalscratch
+        ascii[a-d] globalascii
+        @@expanded @@globalexpanded @(EA)+
+        [be]group par next nextnext (do)+command
+        \!\!(width|height|depth|plus|minus|to)
     /.split
 
     # let's ignore \dimendef etc
 
-    @@primitives_def = "def|edef|xdef|gdef|let|newcount|newdimen|newskip|newbox|newtoks|newmarks|chardef|mathchardef|newconditional"
+    @@primitives_def = %q/
+         def edef xdef gdef let
+         newcount newdimen newskip newbox newtoks newmarks newif newinsert newmuskip
+         chardef mathchardef dimendef countdef toksdef
+         newconditional definecomplexorsimple definecomplexorsimpleempty
+         newcounter newpersistentmark
+         installinsertion installspecial\s*\\[* installoutput\s*\\[*
+    /.split
 
-    @@cs_global  = [@@cs_tex,@@cs_etex,@@cs_pdftex,@@cs_omega].sort.flatten
-    @@types      = [['invalid','*'],['okay','='],['forward','>'],['backward','<'],['unknown','?']]
+    @@types = [['invalid','*'],['okay','='],['forward','>'],['backward','<'],['unknown','?']]
+
+    @@skips = /^(#{@@cs_skip.join('|')})/o
+
+    def initialize(logger=nil,compact=false)
+        @defined      = Hash.new
+        @definitive   = Hash.new
+        @used_before  = Hash.new
+        @used_after   = Hash.new
+        @dependencies = Hash.new
+        @fineorder    = Hash.new
+        @forward      = Hash.new
+        @backward     = Hash.new
+        @disorder     = Hash.new
+        @disordercs   = Hash.new
+        @type         = Hash.new
+        @filename     = 'context.tex'
+        @files        = Array.new # keep load order !
+        @order        = Hash.new
+        @logger       = logger
+        @filefilter   = nil
+        @namefilter   = nil
+        @compact      = compact
+        #
+        @@cs_tex.each     do |cs| @defined[cs] = ['-tex--------'] end
+        @@cs_etex.each    do |cs| @defined[cs] = ['-etex-------'] end
+        @@cs_pdftex.each  do |cs| @defined[cs] = ['-pdftex-----'] end
+        @@cs_omega.each   do |cs| @defined[cs] = ['-omega------'] end
+        @@cs_xetex.each   do |cs| @defined[cs] = ['-xetex------'] end
+        @@cs_metatex.each do |cs| @defined[cs] = ['-metatex----'] end
+    end
 
-    def initialize(logger=nil)
-        @cs_local = Hash.new
-        @cs_new   = Hash.new
-        @cs_defd  = Hash.new
-        @cs_used  = Hash.new
-        @filename = 'context.tex'
-        @files    = Array.new # keep load order !
-        @compact  = false
-        @logger   = logger
+    def report(str)
+        @logger.report(str) rescue false
     end
 
-    def load(filename='context.tex',omitlist=['mult-com.tex'])
+    def setfilter(data)
+        data.split(/\s*\,\s*/).each do |d|
+            if d =~ /\.tex$/ then
+                @filefilter = Array.new unless @filefilter
+                @filefilter << d
+            else
+                @namefilter = Array.new unless @namefilter
+                @namefilter << d
+            end
+        end
+    end
+
+    def load(filename='context.tex')
         begin
             @filename = filename
+            n = 0
             File.open(filename) do |f|
                 f.each do |line|
-                    if line =~ /^\\input\s+(\S+)\s*/o then
-                        @files.push($1) unless omitlist.include?(File.basename($1))
+                    if line =~ /^(\\input\s+|\\load[a-z]+\{)([a-z\-\.]+)(\}*)/ then
+                        ante, name, post = $1, $2, $3
+                        @files.push(name)
+                        @order[name] = n += 1
                     end
                 end
             end
         rescue
             @files = Array.new
+            @order = Hash.new
+        end
+    end
+
+    def save(filename='context.tex')
+        unless @filefilter || @namefilter then
+            begin
+                data = IO.readlines(filename).each do |line|
+                    line.gsub!(/^(\\input\s+|\\load[a-z]+\{)([a-z\-\.]+)(\}*)\s*$/) do
+                        ante, name, post = $1, $2, $3
+                        fin = (@fineorder[name]    || [])-[name]
+                        dep = (@dependencies[name] || [])-[name]
+                        dis = (@disorder[name]     || [])-[name]
+                        fin = if fin.size > 0 then " B[#{fin.join(' ')}]" else "" end
+                        dep = if dep.size > 0 then " A[#{dep.join(' ')}]" else "" end
+                        dis = if dis.size > 0 then " D[#{dis.join(' ')}]" else "" end
+                        "#{ante}#{name}#{post} %#{fin}#{dep}#{dis}\n"
+                    end
+                end
+            rescue
+                report("error: #{$!}")
+            else
+                begin
+                    newname = filename.sub(/\..*$/,'.log')
+                    report("")
+                    report("writing to #{newname}")
+                    report("")
+                    File.open(newname,'w') do |f|
+                        f << data
+                    end
+                rescue
+                    report("error: #{$!}")
+                end
+            end
         end
     end
 
     def analyze
+        report('')
+        report("loading files")
+        report('')
+        n = 0
         @files.each do |filename|
             if f = File.open(filename) then
-                @logger.report("loading #{filename}") if @logger
-                defs, uses, n = 0, 0, 0
+                defs, uses, l = 0, 0, 0
+                n += 1
+                report("#{n.to_s.rjust(5,' ')} #{filename}")
                 f.each do |line|
-                    n += 1
+                    l += 1
+                    line.chomp!
+
+
+                    line.sub!(/\%.*$/, '')
+                    line.gsub!(/\\(unexpanded|unprotected|global|protected|long)\s*(\\)/, "\\")
+                    # the superseded, overloaded, forwarded, and predefined macros
+                    # are at the outer level anyway, so there we may ignore leading
+                    # spaces (could be inside an \if); other definitions are only
+                    # accepted when they start at the beginning of a line
                     case line
-                        when /^%/
-                            # skip
-                        when /\\newif\s*\\if([a-zA-Z@\?\!]+)/ then
-                            pushdef(filename,n,"if:#{$1}")
-                        when /\\([a-zA-Z@\?\!]+)(true|false)/ then
-                            pushuse(filename,n,"if:#{$1}")
-                        when /^\s*\\(#{@primitives_def})\\([a-zA-Z@\?\!]{3,})/o
-                            pushdef(filename,n,$2)
-                        when /\\([a-zA-Z@\?\!]{3,})/o
-                            pushuse(filename,n,$1)
+                        when /^\\ifx\s*\\[a-zA-Z\@\!\?]+\s*\\undefined\s*(\\else)*(.*?)$/ then
+                            if $2 =~ /^\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})/o then
+                                pushdef(filename,l,$2,5) # kind of auto-predefined
+                            end
+                        when /^\s*\\superseded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,1)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\overloaded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,2)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\forwarded\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,3)
+                            moreuse(filename,l,rest)
+                        when /^\s*\\predefined\s*\\(#{@@primitives_def.join('|')})\s*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3
+                            pushdef(filename,l,name,4)
+                            moreuse(filename,l,rest)
+                        when /^\\(#{@@primitives_def.join('|')})[\=\s]*\\([a-zA-Z\@\?\!]{3,})(.*)$/o
+                            name, rest = $2, $3 # \=* catches the \let \a = \b
+                            pushdef(filename,l,name,0)
+                            moreuse(filename,l,rest)
+                        when /\\newevery\s*\\([a-zA-Z\@\?\!]+)\s*\\([a-zA-Z\@\?\!]+)/ then
+                            a, b = $1, $2
+                            pushdef(filename,l,a,0)
+                            pushdef(filename,l,b,0)
+                        else
+                            moreuse(filename,l,line)
                     end
                 end
                 f.close
             end
         end
+        @used_after.each do |cs,files|
+            (@defined[cs] || []).each do |name|
+                @dependencies[name] = Array.new unless @dependencies[name]
+                files.each do |file|
+                    @dependencies[name] << file unless @dependencies[name].include?(file)
+                end
+            end
+        end
+        @used_before.each do |cs,files|
+            (@defined[cs] || []).each do |name|
+                @disorder[name]   = Array.new unless @disorder[name]
+                @disordercs[name] = Array.new unless @disordercs[name]
+                @fineorder[name]  = Array.new unless @fineorder[name]
+                files.each do |file|
+                    unless @disorder[name].include?(file) || name == file then
+                        unless @defined[cs].include?(file) then
+                            if @order[name] > @order[file] then
+                                @disorder[name]   << file
+                                @disordercs[name] << "#{file}:#{cs}"
+                            end
+                        end
+                    end
+                    @fineorder[name] << file unless @fineorder[name].include?(file) || name == file
+                end
+            end
+        end
     end
 
-    def feedback(compact=false)
+    def moreuse(filename,l,line)
+        line.scan(/\\if([a-zA-Z@\?\!]{3,})/) do |name, rest| # rest, else array
+            pushuse(filename,l,"if#{name}") unless name =~ /^(true|false)$/
+        end
+        line.scan(/\\([a-zA-Z@\?\!]{3,})/) do |name, rest| # rest, else array
+            if name =~ /(true|false)$/ then
+                pushuse(filename,l,"if#{name}") unless name =~ /^(if|set)$/
+            else
+                pushuse(filename,l,name)
+            end
+        end
+    end
+
+    def feedback
         begin
-            outputfile = File.basename(@filename).sub(/\.tex$/,'')+'.dep'
-            File.open(outputfile,'w') do |f|
-                @compact = compact
-                @logger.report("saving analysis in #{outputfile}") if @logger
-                list, len = @cs_local.keys.sort, 0
-                if @compact then
-                    list.each do |cs|
-                        if cs.length > len then len = cs.length end
+            # get max length
+            l = 0
+            list = @defined.keys.sort
+            list.each do |cs|
+                l = cs.length if cs.length > l
+            end
+            if ! @compact then
+                n = 0
+                report('')
+                report("defined: #{@defined.size}")
+                report('')
+                @defined.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter && ! @defined[cs].include?(cs)
+                    if @defined[cs].size > 1 then
+                        dlist = @defined[cs].collect do |d|
+                            if d == @definitive[cs] then d else "[#{d}]" end
+                        end
+                    else
+                        dlist = @defined[cs]
                     end
-                    len += 1
-                else
-                    f.puts "<?xml version='1.0'?>\n"
-                    f.puts "<dependencies xmlns='http://www.pragma-ade.com/schemas/texdeps.rng' rootfile='#{@filename}'>\n"
+                    report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{dlist.join(' ')}")
                 end
-                list.each do |cs|
-                    if @cs_new.key?(cs) then
-                        if @cs_new[cs] == @cs_local[cs] then
-                            f.puts some_struc(cs,len,1,some_str(@cs_new,@cs_defd,cs))
-                        elsif @cs_new[cs].first == @cs_local[cs].first then
-                            f.puts some_struc(cs,len,2,some_str(@cs_new,@cs_defd,cs),some_str(@cs_local,@cs_used,cs))
-                        else
-                            f.puts some_struc(cs,len,3,some_str(@cs_new,@cs_defd,cs),some_str(@cs_local,@cs_used,cs))
-                        end
+            end
+            if true then
+                n = 0
+                report('')
+                report("used before defined: #{@used_before.size}")
+                report('')
+                @used_before.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter && (@used_before[cs] & @filefilter).size == 0
+                    used = @used_before[cs] - (@defined[cs] || [])
+                    defined = (@defined[cs] || []).join(' ')
+                    defined = "[ ? ]" if defined.empty?
+                    if used.size > 0 then
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined} -> #{used.join(' ')}")
                     else
-                        f.puts some_struc(cs,len,4,some_str(@cs_local,@cs_used,cs))
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined}")
                     end
                 end
-                if @compact then
-                    # nothing
-                else
-                    "</dependencies>\n" unless @compact
+                report('      none') if n == 0
+            end
+            if ! @compact then
+                n = 0
+                report('')
+                report("used after defined: #{@used_after.size}")
+                report('')
+                @used_after.keys.sort.each do |cs|
+                    next if @namefilter && ! @namefilter.include?(cs)
+                    next if @filefilter &&  (@used_after[cs] & @filefilter).size == 0
+                    used = @used_after[cs] - (@defined[cs] || [])
+                    defined = (@defined[cs] || []).join(' ')
+                    if used.size > 0 then
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined} <- #{used.join(' ')}")
+                    else
+                        report("#{(n += 1).to_s.rjust(5,' ')} #{cs.ljust(l,' ')} == #{defined}")
+                    end
+                end
+                report('      none') if n == 0
+            end
+            if ! @compact then
+                unless @filefilter || @namefilter then
+                    [false,true].each do |mode|
+                        n = 0
+                        report("")
+                        report("file dependecies #{if mode then '(critical)' end}")
+                        [@dependencies].each do |dependencies|
+                            report("")
+                            dependencies.keys.sort.each do |f|
+                                if dependencies[f].size > 0 then
+                                    dependencies[f].delete(f)
+                                end
+                                if mode then
+                                    dep = dependencies[f].delete_if do |d|
+                                        f[0..3] == d[0..3] # same xxxx- prefix
+                                    end
+                                else
+                                    dep = dependencies[f]
+                                end
+                                if dep.size > 0 then
+                                    name = f.nosuffix('tex').ljust(8,' ')
+                                    list = dep.sort.collect do |k| k.nosuffix('tex') end
+                                    report("#{(n += 1).to_s.rjust(5,' ')} #{name} !! #{list.join(' ')}")
+                                end
+                            end
+                        end
+                        report('      none') if n == 0
+                    end
+                end
+            end
+            if true then
+                unless @filefilter || @namefilter then
+                    [false,true].each do |mode|
+                        [@disorder,@disordercs].each do |disorder|
+                            n = 0
+                            report("")
+                            report("file disorder #{if mode then '(critical)' end}")
+                            report("")
+                            disorder.keys.sort.each do |f|
+                                if disorder[f].size > 0 then
+                                    disorder[f].delete(f)
+                                end
+                                if mode then
+                                    dis = disorder[f].delete_if do |d|
+                                        f[0..3] == d[0..3] # same xxxx- prefix
+                                    end
+                                else
+                                    dis = disorder[f]
+                                end
+                                if dis.size > 0 then
+                                    name = f.nosuffix('tex').ljust(8,' ')
+                                    list = dis.sort.collect do |k| k.nosuffix('tex') end
+                                    report("#{(n += 1).to_s.rjust(3,' ')} #{name} ?? #{list.join(' ')}")
+                                end
+                            end
+                        end
+                        report('      none') if n == 0
+                    end
                 end
             end
         rescue
+            puts("fatal error: #{$!} #{$@.join("\n")}")
         end
     end
 
     private
 
-    def some_struc(cs,len,type=1,defstr='',usestr='')
-        if @compact then
-            "#{cs.ljust(len)} #{@@types[type][1]} #{defstr} #{usestr}"
-        else
-            "<macro name='#{cs}' type='#{type}'>\n" +
-            if defstr.empty? then "  <defined/>\n" else "  <defined>\n#{defstr}  <\defined>\n" end +
-            if usestr.empty? then "  <used/>\n"    else "  <used>#{usestr}\n  <\used>\n" end +
-            "</macro>\n"
-        end
+    def csdefined?(cs,filename)
+        @defined[cs] && @defined[cs].include?(filename)
+    end
+    def csbefore?(cs,filename)
+        @used_before[cs] && @used_before[cs].include?(filename)
+    end
+    def csafter?(cs,filename)
+        @used_after[cs] && @used_after[cs].include?(filename)
     end
 
-    def some_str(files, lines, cs)
-        return '' unless files[cs]
-        if @compact then
-            str = '[ '
-            files[cs].each do |c|
-                str += c
-                str += " (#{lines[cs][c].join(' ')}) " if lines[cs][c]
-                str += ' '
-            end
-            str += ']'
-            str.gsub(/ +/, ' ')
-        else
-            str = ''
-            files[cs].each do |c|
-                if lines[cs][c] then
-                    str += "    <file name='#{c}'>\n"
-                    str += "      "
-                    lines[cs][c].each do |l|
-                        # str += "      <line n='#{l}'/>\n"
-                        str += "<line n='#{l}'/>"
-                    end
-                    str += "\n"
-                    str += "    </file>\n"
-                else
-                    str += "    <file name='#{c}'/>\n"
-                end
-            end
-            str
-        end
+    def csignored?(cs)
+        cs.to_s =~ @@skips
     end
 
-    def pushdef(filename,n,cs)
-        unless @cs_new.key?(cs) then
-            @cs_new[cs] = Array.new
-            @cs_defd[cs] = Hash.new unless @cs_defd.key?(cs)
+    def pushdef(filename,n,cs,type)
+        if csignored?(cs) then
+            # nothing
+        elsif @defined[cs] then
+            case type
+                when 5 then
+                    # if test, no definition done
+                else
+                    @definitive[cs] = filename
+                    unless @filefilter || @namefilter then
+                        report("#{cs} is redefined") unless csdefined?(cs,filename) || @compact
+                    end
+            end
+            @defined[cs] << filename unless @defined[cs].include?(filename)
+        else
+            @defined[cs] = Array.new
+            @defined[cs] << filename
+            @definitive[cs] = filename
+            @type[cs] = type
         end
-        @cs_defd[cs][filename] = Array.new unless @cs_defd[cs][filename]
-        @cs_new[cs].push(filename) unless @cs_new[cs].include?(filename)
-        @cs_defd[cs][filename] << n
     end
 
     def pushuse(filename,n,cs)
-        unless @@cs_global.include?(cs.to_s) then
-            unless @cs_local[cs] then
-                @cs_local[cs] = Array.new
-                @cs_used[cs] = Hash.new unless @cs_used.key?(cs)
-            end
-            @cs_used[cs][filename] = Array.new unless @cs_used[cs][filename]
-            @cs_local[cs].push(filename) unless @cs_local[cs].include?(filename)
-            @cs_used[cs][filename] << n
+        if csignored?(cs) then
+            # nothing
+        elsif @defined[cs] then
+            @used_after[cs] = Array.new unless @used_after[cs]
+            @used_after[cs] << filename unless csafter?(cs,filename)
+        else
+            @used_before[cs] = Array.new unless @used_before[cs]
+            @used_before[cs] << filename unless csbefore?(cs,filename)
         end
     end
 
@@ -2271,9 +2514,9 @@ class Commands
         filename = if @commandline.arguments.empty? then 'context.tex' else @commandline.arguments.first end
         compact  = @commandline.option('compact')
 
-        ['progname=context',''].each do |progname|
+        ['context',''].each do |progname|
             unless FileTest.file?(filename) then
-                name = `kpsewhich #{progname} #{filename}`.chomp
+                name = Kpse.found(filename, progname)
                 if FileTest.file?(name) then
                     filename = name
                     break
@@ -2281,10 +2524,12 @@ class Commands
             end
         end
 
-        if FileTest.file?(filename) && deps = TexDeps.new(logger) then
+        if FileTest.file?(filename) && deps = TexDeps.new(logger,compact) then
+            deps.setfilter(@commandline.option('filter'))
             deps.load
             deps.analyze
-            deps.feedback(compact)
+            deps.feedback
+            deps.save if @commandline.option('save')
         else
             report("unknown file #{filename}")
         end
@@ -2365,9 +2610,9 @@ class Commands
         end
 
         def locatedlocaltree
-            tree = `kpsewhich --expand-path $TEXMFLOCAL`.chomp rescue nil
+            tree = Kpse.used_path('TEXMFLOCAL')
             unless tree && FileTest.directory?(tree) then
-                tree = `kpsewhich --expand-path $TEXMF`.chomp rescue nil
+                tree = Kpse.used_path('TEXMF')
             end
             return tree
         end
@@ -2377,7 +2622,8 @@ class Commands
                  report("fatal error, '#{archive}' has not been downloaded")
                  return false
             end
-            unless system("unzip -uo #{archive}") then
+            # unless system("unzip -uo #{archive}") then
+            unless system("unzip -o #{archive}") then
                 report("fatal error, make sure that you have 'unzip' in your path")
                 return false
             end
@@ -2441,15 +2687,18 @@ commandline.registeraction('dpxmapfiles'       , 'convert pdftex mapfiles to dvi
 commandline.registeraction('listentities'      , 'create doctype entity definition from enco-uc.tex')
 commandline.registeraction('brandfiles'        , 'add context copyright notice [--force]')
 commandline.registeraction('platformize'       , 'replace line-endings [--recurse --force] [pattern]')
-commandline.registeraction('dependencies'      , 'analyze depedencies witin context [--compact] [rootfile]')
+commandline.registeraction('dependencies'      , 'analyze depedencies within context [--save --compact --filter=[macros|filenames]] [filename]')
 commandline.registeraction('updatecontext'     , 'download latest version and remake formats')
 commandline.registeraction('disarmutfbom'      , 'remove utf bom [--force]')
 
 commandline.registervalue('type','')
+commandline.registervalue('filter','')
 
 commandline.registerflag('recurse')
 commandline.registerflag('force')
+commandline.registerflag('compact')
 commandline.registerflag('pipe')
+commandline.registerflag('save')
 commandline.registerflag('all')
 commandline.registerflag('xml')
 commandline.registerflag('log')
diff --git a/scripts/context/ruby/pdftools.rb b/scripts/context/ruby/pdftools.rb
index 8a62a0487..d40e2d852 100644
--- a/scripts/context/ruby/pdftools.rb
+++ b/scripts/context/ruby/pdftools.rb
@@ -15,10 +15,7 @@
 
 banner = ['PDFTools', 'version 1.2.1', '2003/2005', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/pstopdf.rb b/scripts/context/ruby/pstopdf.rb
index 197f83961..a677cb617 100644
--- a/scripts/context/ruby/pstopdf.rb
+++ b/scripts/context/ruby/pstopdf.rb
@@ -12,7 +12,7 @@
 
 banner = ['PsToPdf', 'version 2.0.1', '2002-2006', 'PRAGMA ADE/POD']
 
-$: << File.expand_path(File.dirname($0))
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 # todo: paden/prefix in magick and inkscape
 # todo: clean up method handling (pass strings, no numbers)
diff --git a/scripts/context/ruby/rlxtools.rb b/scripts/context/ruby/rlxtools.rb
index 1225dedb3..40a45bd51 100644
--- a/scripts/context/ruby/rlxtools.rb
+++ b/scripts/context/ruby/rlxtools.rb
@@ -12,10 +12,7 @@
 
 banner = ['RlxTools', 'version 1.0.1', '2004/2005', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
@@ -98,6 +95,9 @@ class Commands
                     if conversion = variables['conversion'] then
                         report("testing for conversion #{conversion}")
                         if suffix = variables['suffix'].downcase then
+                            if ! suffix.empty? && variables['file'] && variables['file'] !~ /\.([a-z]+)$/i then
+                                variables['file'] += ".#{suffix}"
+                            end
                             if file = variables['file'] then
                                 report("conversion #{conversion} for suffix #{suffix} for file #{file}")
                             else
@@ -251,17 +251,43 @@ class Commands
 
     include CommandBase
 
-    def identify
-        @commandline.arguments.each do |filename|
-            if state = do_identify(filename) then
-                begin
-                    File.open(filename+'.rli','w') do |f|
-                        f << state
+    @@xmlbanner = "<?xml version='1.0' standalone='yes'?>"
+
+    def identify(resultfile='rlxtools.rli')
+        if @commandline.option('collect') then
+            begin
+                File.open(resultfile,'w') do |f|
+                    f << "#{@@xmlbanner}\n"
+                    f << "<rl:identification>\n"
+                    @commandline.arguments.each do |filename|
+                        if state = do_identify(filename) then
+                            report("#{filename} is identified")
+                            f << state
+                        else
+                            report("unable to identify #{filename}")
+                        end
+                    end
+                    f << "</rl:identification>\n"
+                    report("result saved in #{resultfile}")
+                end
+            rescue
+                report("error in writing result")
+            end
+        else
+            @commandline.arguments.each do |filename|
+                if state = do_identify(filename) then
+                    begin
+                        File.open(filename+'.rli','w') do |f|
+                            f << "#{@@xmlbanner}\n"
+                            f << state
+                        end
+                    rescue
+                        report("error in identifying #{filename}")
+                    else
+                        report("#{filename} is identified")
                     end
-                rescue
-                    report("error in identifying #{filename}")
                 else
-                    report("#{filename} is identified")
+                    report("unable to identify #{filename}")
                 end
             end
         end
@@ -269,11 +295,15 @@ class Commands
 
     private
 
-    def do_identify(filename)
+    def do_identify(filename,centimeters=false)
         begin
             str = nil
             if FileTest.file?(filename) then
-                result = `identify -format \"x=%x,y=%y,w=%w,h=%h,b=%b\" #{filename}`.chomp.split(',')
+                if centimeters then
+                    result = `identify -units PixelsPerCentimeter -format \"x=%x,y=%y,w=%w,h=%h,b=%b\" #{filename}`.chomp.split(',')
+                else
+                    result = `identify -units PixelsPerInch       -format \"x=%x,y=%y,w=%w,h=%h,b=%b\" #{filename}`.chomp.split(',')
+                end
                 tags = Hash.new
                 result.each do |r|
                     if rr = r.split("=") then
@@ -285,7 +315,6 @@ class Commands
                 height = unified(tags['h']||0,tags['y']||'1')
                 if size > 0 then
                     str = ''
-                    str << "<?xml version='1.0' standalone='yes'?>\n"
                     str << "<rl:identify name='#{File.basename(filename)}'>\n"
                     str << "  <rl:size>#{size}</rl:size>\n"
                     str << "  <rl:path>#{File.dirname(filename).sub(/\\/o,'/')}</rl:path>\n"
@@ -322,13 +351,14 @@ end
 logger      = Logger.new(banner.shift)
 commandline = CommandLine.new
 
-commandline.registeraction('manipulate', ' [--test] manipulatorfile resourselog')
-commandline.registeraction('identify', 'filename')
+commandline.registeraction('manipulate', '[--test] manipulatorfile resourselog')
+commandline.registeraction('identify'  , '[--collect] filename')
 
 commandline.registeraction('help')
 commandline.registeraction('version')
 
 commandline.registerflag('test')
+commandline.registerflag('collect')
 
 commandline.expand
 
diff --git a/scripts/context/ruby/texexec.rb b/scripts/context/ruby/texexec.rb
index 1a7175f23..f1c8059c9 100644
--- a/scripts/context/ruby/texexec.rb
+++ b/scripts/context/ruby/texexec.rb
@@ -1,9 +1,6 @@
 banner = ['TeXExec', 'version 6.2.0', '1997-2006', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'ftools'     # needed ?
 
@@ -97,6 +94,16 @@ class Commands
         end
     end
 
+    def mpstatic
+        if job = TEX.new(logger) then
+            job.setvariable('filename',@commandline.arguments.first)
+            prepare(job)
+            job.processmpstatic
+            job.inspect && Kpse.inspect  if @commandline.option('verbose')
+            exit 1 if job.error?
+        end
+    end
+
     # hard coded goodies # to be redone as s-ctx-.. with vars passed as such
 
     def listing
@@ -143,21 +150,21 @@ class Commands
     end
 
     def figures
-        # this one will be redone using rlxtools
+        # we replaced "texutil --figures ..."
         if job = TEX.new(logger) then
             prepare(job)
             job.cleanuptemprunfiles
             files = @commandline.arguments.sort
             if files.length > 0 then
                 if f = File.open(job.tempfilename('tex'),'w') then
-                    # will be replaced, does not work any more
-                    Kpse.runscript('texutil.pl',files.join(' '),'--figures')
+                    Kpse.runscript('rlxtools', ['--identify','--collect'], files.join(' '))
                     figures     = @commandline.checkedoption('method', 'a').downcase
                     paperoffset = @commandline.checkedoption('paperoffset', '0pt')
                     backspace   = @commandline.checkedoption('backspace', '1.5cm')
                     topspace    = @commandline.checkedoption('topspace', '1.5cm')
                     boxtype     = @commandline.checkedoption('boxtype','')
                     f << "% format=english\n";
+                    f << "\\usemodule[res-20]\n"
                     f << "\\setuplayout\n";
                     f << "  [topspace=#{topspace},backspace=#{backspace},\n"
                     f << "   header=1.5cm,footer=0pt,\n";
@@ -175,10 +182,9 @@ class Commands
                     f.close
                     job.setvariable('interface','english')
                     job.setvariable('simplerun',true)
-                    # job.setvariable('nooptionfile',true)
                     job.setvariable('files',[job.tempfilename])
                     job.processtex
-                    File.silentdelete('texutil.tuf')
+                    # File.silentdelete('rlxtools.rli') unless job.getvariable('keep')
                 else
                     report('no figures to show')
                 end
@@ -194,7 +200,7 @@ class Commands
             prepare(job)
             job.cleanuptemprunfiles
             files = @commandline.arguments.sort
-            msuffixes = ['tex','mp','pl','pm','rb']
+            msuffixes = ['tex','mkii','mkiv','mp','pl','pm','rb']
             if files.length > 0 then
                 files.each do |fname|
                     fnames = Array.new
@@ -208,6 +214,11 @@ class Commands
                     fnames.each do |ffname|
                         if msuffixes.include?(File.splitname(ffname)[1]) && FileTest.file?(ffname) then
                             if mod = File.open(job.tempfilename('tex'),'w') then
+if File.suffix(ffname) =~ /^(mkii|mkiv)$/o then
+    markfile = $1
+else
+    markfile = nil
+end
                                 Kpse.runscript('ctxtools',ffname,'--document')
                                 if ted = File.silentopen(File.suffixed(ffname,'ted')) then
                                     firstline = ted.gets
@@ -220,7 +231,7 @@ class Commands
                                 else
                                     mod << "% interface=en\n"
                                 end
-                                mod << "\\usemodule[abr-01,mod-01]\n"
+                                mod << "\\usemodule[mod-01]\n"
                                 mod << "\\def\\ModuleNumber{1}\n"
                                 mod << "\\starttext\n"
                                 # todo: global file too
@@ -231,10 +242,15 @@ class Commands
                                 job.setvariable('simplerun',true)
                                 # job.setvariable('nooptionfile',true)
                                 job.setvariable('files',[job.tempfilename])
+result = File.unsuffixed(File.basename(ffname))
+if markfile then
+    result = result+'-'+markfile
+end
+job.setvariable('result',result)
                                 job.processtex
-                                ["dvi", "pdf","tuo"].each do |s|
-                                    File.silentrename(job.tempfilename(s),File.suffixed(ffname,s));
-                                end
+                                # ["dvi", "pdf","ps"].each do |s|
+                                    # File.silentrename(job.tempfilename(s),File.suffixed(ffname,s));
+                                # end
                             end
                         end
                     end
@@ -246,6 +262,39 @@ class Commands
         end
     end
 
+    def pdfsplit
+        if job = TEX.new(logger) then
+            prepare(job)
+            job.cleanuptemprunfiles
+            filename = File.expand_path(@commandline.arguments.first)
+            if FileTest.file?(filename) then
+                basename = filename.sub(/\..*?$/,'')
+                tempfile = File.suffixed(job.tempfilename,'tex')
+                if basename != filename then
+                    info = `pdfinfo #{filename}`
+                    if info =~ /Pages:\s*(\d+)/ then
+                        nofpages = $1.to_i
+                        nofpages.times do |i|
+                            if f = File.open(tempfile,"w") then
+                                n = i + 1
+                                report("extracting page #{n}")
+                                f << "\\starttext\\startTEXpage\n"
+                                f << "\\externalfigure[#{filename}][object=no,page=#{n}]\n"
+                                f << "\\stopTEXpage\\stoptext\n"
+                                f.close
+                                job.setvariable('interface','english') # redundant
+                                job.setvariable('simplerun',true)
+                                job.setvariable('files',[tempfile])
+                                job.processtex
+                            end
+                        end
+                    end
+                end
+            end
+            job.cleanuptemprunfiles
+        end
+    end
+
     def arrangeoutput
         if job = TEX.new(logger) then
             prepare(job)
@@ -391,8 +440,8 @@ class Commands
                             f <<  "]\n"
                             f <<  "\\definepapersize\n"
                             f <<  "  [copy]\n"
-                            f <<  "  [width=\\naturalfigurewidth,\n"
-                            f <<  "   height=\\naturalfigureheight]\n"
+                            f <<  "  [width=\\figurewidth,\n"
+                            f <<  "   height=\\figureheight]\n"
                             f <<  "\\setuppapersize\n"
                             f <<  "  [copy][copy]\n"
                             f <<  "\\setuplayout\n"
@@ -578,6 +627,7 @@ commandline.registeraction('process',   'process file')
 commandline.registeraction('mptex',     'process mp file')
 commandline.registeraction('mpxtex',    'process mpx file')
 commandline.registeraction('mpgraphic', 'process mp file to stand-alone graphics')
+commandline.registeraction('mpstatic',  'process mp/ctx file to stand-alone graphics')
 
 commandline.registeraction('listing',    'list of file content')
 commandline.registeraction('figures',    'generate overview of figures')
@@ -587,6 +637,7 @@ commandline.registeraction('pdfselect',  'select pages from file(s)')
 commandline.registeraction('pdfcopy',    'copy pages from file(s)')
 commandline.registeraction('pdftrim',    'trim pages from file(s)')
 commandline.registeraction('pdfcombine', 'combine multiple pages')
+commandline.registeraction('pdfsplit',   'split file in pages')
 
 # compatibility switch
 
diff --git a/scripts/context/ruby/texmfstart.rb b/scripts/context/ruby/texmfstart.rb
index 411cb9248..b9ced8813 100644
--- a/scripts/context/ruby/texmfstart.rb
+++ b/scripts/context/ruby/texmfstart.rb
@@ -31,9 +31,7 @@
 
 # we don't depend on other libs
 
-$ownpath = File.expand_path(File.dirname($0)) unless defined? $ownpath
-
-$: << $ownpath
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require "rbconfig"
 require "md5"
@@ -176,6 +174,8 @@ end
 # concept   : Hans Hagen
 # info      : j.hagen@xs4all.nl
 
+# todo: multiple cnf files
+#
 
 class String
 
@@ -1429,7 +1429,8 @@ end
 
 $mswindows = Config::CONFIG['host_os'] =~ /mswin/
 $separator = File::PATH_SEPARATOR
-$version   = "2.0.0"
+$version   = "2.0.2"
+$ownpath   = File.dirname($0)
 
 if $mswindows then
     require "win32ole"
@@ -1473,6 +1474,8 @@ $predefined['pdftools'] = 'pdftools.rb'
 $predefined['mpstools'] = 'mpstools.rb'
 $predefined['exatools'] = 'exatools.rb'
 $predefined['xmltools'] = 'xmltools.rb'
+$predefined['luatools'] = 'luatools.lua'
+$predefined['mtxtools'] = 'mtxtools.rb'
 
 $predefined['newpstopdf']   = 'pstopdf.rb'
 $predefined['newtexexec']   = 'texexec.rb'
@@ -1497,6 +1500,8 @@ $makelist = [
     'exatools',
     'runtools',
     'rlxtools',
+    'luatools',
+    'mtxtools',
     #
     # no, 'texmfstart'
 ]
@@ -1509,31 +1514,36 @@ $makelist = [
 $scriptlist   = 'rb|pl|py|lua|jar'
 $documentlist = 'pdf|ps|eps|htm|html'
 
-$editor = ENV['TEXMFSTART_EDITOR'] || ENV['EDITOR'] || ENV['editor'] || 'scite'
+$editor       = ENV['TEXMFSTART_EDITOR'] || ENV['EDITOR'] || ENV['editor'] || 'scite'
 
-$crossover = true # to other tex tools, else only local
+$crossover    = true # to other tex tools, else only local
+$kpse         = nil
 
-$applications['unknown']  = ''
-$applications['perl']     = $applications['pl']  = 'perl'
-$applications['ruby']     = $applications['rb']  = 'ruby'
-$applications['python']   = $applications['py']  = 'python'
-$applications['lua']      = $applications['lua'] = 'lua'
-$applications['java']     = $applications['jar'] = 'java'
+def set_applications(page=1)
 
-if $mswindows then
-    $applications['pdf']  = ['',"pdfopen --page #{$page} --file",'acroread']
-    $applications['html'] = ['','netscape','mozilla','opera','iexplore']
-    $applications['ps']   = ['','gview32','gv','gswin32','gs']
-else
-    $applications['pdf']  = ["pdfopen --page #{$page} --file",'acroread']
-    $applications['html'] = ['netscape','mozilla','opera']
-    $applications['ps']   = ['gview','gv','gs']
-end
+    $applications['unknown']  = ''
+    $applications['perl']     = $applications['pl']  = 'perl'
+    $applications['ruby']     = $applications['rb']  = 'ruby'
+    $applications['python']   = $applications['py']  = 'python'
+    $applications['lua']      = $applications['lua'] = 'lua'
+    $applications['java']     = $applications['jar'] = 'java'
 
-$applications['htm']      = $applications['html']
-$applications['eps']      = $applications['ps']
+    if $mswindows then
+        $applications['pdf']  = ['',"pdfopen --page #{page} --file",'acroread']
+        $applications['html'] = ['','netscape','mozilla','opera','iexplore']
+        $applications['ps']   = ['','gview32','gv','gswin32','gs']
+    else
+        $applications['pdf']  = ["pdfopen --page #{page} --file",'acroread']
+        $applications['html'] = ['netscape','mozilla','opera']
+        $applications['ps']   = ['gview','gv','gs']
+    end
 
-$kpse = nil
+    $applications['htm']      = $applications['html']
+    $applications['eps']      = $applications['ps']
+
+end
+
+set_applications()
 
 def check_kpse
     if $kpse then
@@ -1795,6 +1805,21 @@ def expanded(arg) # no "other text files", too restricted
     end
 end
 
+def changeddir?(path)
+    if path.empty? then
+        return true
+    else
+        begin
+            Dir.chdir(path) if ! path.empty?
+        rescue
+            report("unable to change to directory: #{path}")
+        else
+            report("changed to directory: #{path}")
+        end
+        return File.expand_path(Dir.getwd) == File.expand_path(path)
+    end
+end
+
 def runcommand(command)
     if $locate then
         command = command.split(' ').collect do |c|
@@ -1810,20 +1835,10 @@ def runcommand(command)
         print command # to stdout and no newline
     elsif $execute then
         report("using 'exec' instead of 'system' call: #{command}")
-        begin
-            Dir.chdir($path) if ! $path.empty?
-        rescue
-            report("unable to chdir to: #{$path}")
-        end
-        exec(command)
+        exec(command) if changeddir?($path)
     else
         report("using 'system' call: #{command}")
-        begin
-            Dir.chdir($path) if ! $path.empty?
-        rescue
-            report("unable to chdir to: #{$path}")
-        end
-        system(command)
+        system(command) if changeddir?($path)
     end
 end
 
@@ -1961,7 +1976,10 @@ def find(filename,program)
         end
         filename.sub!(/^.*[\\\/]/, '')
         # next we look at the current path and the callerpath
-        [['.','current'],[$ownpath,'caller'],[registered("THREAD"),'thread']].each do |p|
+        [ ['.','current'],
+          [$ownpath,'caller'], ["#{$ownpath}/../#{suffixlist[0]}",'caller'],
+          [registered("THREAD"),'thread'], ["#{registered("THREAD")}/../#{suffixlist[0]}",'thread'],
+        ].each do |p|
             if p && ! p.empty? && ! (p[0] == 'unknown') then
                 suffixlist.each do |suffix|
                     fname = "#{filename}.#{suffix}"
@@ -2125,9 +2143,9 @@ def find(filename,program)
             return ''
         end
     rescue
-        # error, trace = $!, $@.join("\n")
-        # report("fatal error: #{error}\n#{trace}")
-        report("fatal error")
+        error, trace = $!, $@.join("\n")
+        report("fatal error: #{error}\n#{trace}")
+        # report("fatal error")
     end
 end
 
@@ -2402,7 +2420,7 @@ def execute(arguments)
     $program     = $directives['program']     || 'context'
     $direct      = $directives['direct']      || false
     $edit        = $directives['edit']        || false
-    $page        = $directives['page']        || 0
+    $page        = $directives['page']        || 1
     $browser     = $directives['browser']     || false
     $report      = $directives['report']      || false
     $verbose     = $directives['verbose']     || false
@@ -2440,6 +2458,8 @@ def execute(arguments)
 
     $verbose = true if (ENV['_CTX_VERBOSE_'] =~ /(y|yes|t|true|on)/io) && ! $locate && ! $report
 
+    set_applications($page)
+
     # private:
 
     $selfmerge   = $directives['selfmerge'] || false
diff --git a/scripts/context/ruby/texsync.rb b/scripts/context/ruby/texsync.rb
index 22b7d46c0..ade307d8e 100644
--- a/scripts/context/ruby/texsync.rb
+++ b/scripts/context/ruby/texsync.rb
@@ -16,10 +16,7 @@
 
 banner = ['TeXSync', 'version 1.1.1', '2002/2004', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/]\w*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/textools.rb b/scripts/context/ruby/textools.rb
index 993388347..345a27572 100644
--- a/scripts/context/ruby/textools.rb
+++ b/scripts/context/ruby/textools.rb
@@ -15,10 +15,7 @@
 
 banner = ['TeXTools', 'version 1.3.1', '2002/2006', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/texutil.rb b/scripts/context/ruby/texutil.rb
index da9a19205..ee0fc1e5e 100644
--- a/scripts/context/ruby/texutil.rb
+++ b/scripts/context/ruby/texutil.rb
@@ -1,9 +1,6 @@
 banner = ['TeXUtil  ', 'version 9.1.0', '1997-2005', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/tmftools.rb b/scripts/context/ruby/tmftools.rb
index 074e949d1..626ef1f4a 100644
--- a/scripts/context/ruby/tmftools.rb
+++ b/scripts/context/ruby/tmftools.rb
@@ -27,10 +27,7 @@
 
 banner = ['TMFTools', 'version 1.1.0 (experimental, no help yet)', '2005/2006', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/www/exa.rb b/scripts/context/ruby/www/exa.rb
index c6d59d864..5e9b3fd82 100644
--- a/scripts/context/ruby/www/exa.rb
+++ b/scripts/context/ruby/www/exa.rb
@@ -145,12 +145,12 @@ class WWW
             dat << "</exa:data>\n"
             if req.empty? then
                 req << "<?xml version='1.0' ?>\n"
-                req << "<exa:request #{@@namespace}'>\n"
+                req << "<exa:request xmlns:exa='#{@@namespace}'>\n"
                 req << "<exa:application>\n"
                 req << "<exa:action>'#{action}</exa:action>\n"     unless action.empty?
                 # req << "<exa:command>'#{command}</exa:command>\n"  unless command.empty?
                 # req << "<exa:url>'#{url}</exa:url>\n"              unless url.empty?
-                req << "<exa:application>\n"
+                req << "</exa:application>\n"
                 req << "<exa:comment>constructed request</exa:comment>\n"
                 req << dat
                 req << "</exa:request>\n"
diff --git a/scripts/context/ruby/www/lib.rb b/scripts/context/ruby/www/lib.rb
index 2a4f3e14f..f5f362b12 100644
--- a/scripts/context/ruby/www/lib.rb
+++ b/scripts/context/ruby/www/lib.rb
@@ -172,8 +172,8 @@ class WWW
         @interface.set('process:os'        , platform)
         @interface.set('process:texos'     , 'texmf-' + platform)
 
-        @interface.set('trace:run'         , 'yes') if (ENV['EXA:TRACE:RUN']    || '') =~ @@re_true
-        @interface.set('trace:errors'      , 'yes') if (ENV['EXA:TRACE:ERRORS'] || '') =~ @@re_true
+        @interface.set('trace:run'         , 'yes') if (ENV['EXA_TRACE_RUN']    || '') =~ @@re_true
+        @interface.set('trace:errors'      , 'yes') if (ENV['EXA_TRACE_ERRORS'] || '') =~ @@re_true
 
         yield self if block_given?
     end
@@ -1276,12 +1276,19 @@ class WWW
         resultname, replyname = 'result.pdf', 'reply.exa'
         replyfile = File.join(tmp,replyname)
         resultfile = File.join(tmp,resultname)
+        targetname = File.join(cache_root,dir,resultname)
+        # make sure that there is no target left in case of an
+        # error; needed in case of given session name
+        if FileTest.directory?(File.join(cache_root,dir)) then
+            File.delete(targetname) rescue false
+        end
+        # now try to locate the file
         if FileTest.file?(fullname) then
             if indirect?(fullname) then
                 begin
+                    # check if directory exists and (if so) delete left overs
                     File.makedirs(File.join(cache_root,dir))
-                    targetname = File.join(cache_root,dir,resultname)
-                    File.delete(targetname) rescue false # left overs
+                    File.delete(targetname) rescue false
                     File.symlink(fullname,targetname) rescue message('Status',$!)
                     unless FileTest.file?(targetname) then
                         FileUtils::cp(fullname,targetname) rescue false
diff --git a/scripts/context/ruby/wwwclient.rb b/scripts/context/ruby/wwwclient.rb
index 8f5451a8d..d41541a09 100644
--- a/scripts/context/ruby/wwwclient.rb
+++ b/scripts/context/ruby/wwwclient.rb
@@ -19,7 +19,7 @@
 
 banner = ['WWWClient', 'version 1.0.0', '2003-2006', 'PRAGMA ADE/POD']
 
-$: << File.dirname(File.expand_path($0))
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/wwwserver.rb b/scripts/context/ruby/wwwserver.rb
index 18ea57df1..53e1cdc51 100644
--- a/scripts/context/ruby/wwwserver.rb
+++ b/scripts/context/ruby/wwwserver.rb
@@ -2,7 +2,7 @@
 
 banner = ['WWWServer', 'version 1.0.0', '2003-2006', 'PRAGMA ADE/POD']
 
-$: << File.dirname(File.expand_path($0))
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
diff --git a/scripts/context/ruby/wwwwatch.rb b/scripts/context/ruby/wwwwatch.rb
index 0afb9a392..0faa45aec 100644
--- a/scripts/context/ruby/wwwwatch.rb
+++ b/scripts/context/ruby/wwwwatch.rb
@@ -2,7 +2,7 @@
 
 banner = ['WWWWatch', 'version 1.0.0', '2003-2006', 'PRAGMA ADE/POD']
 
-$: << File.dirname(File.expand_path($0))
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
@@ -46,6 +46,7 @@ class Watch < Monitor
         @logger      = logger
         @verbose     = false
         @create      = false
+        @onlyonerun  = false
         # [:INT, :TERM, :EXIT].each do |signal|
             # trap(signal) do
                 # kill
@@ -100,7 +101,7 @@ class Watch < Monitor
             exit! rescue false # no checking, no at_exit done
         end
         unless File.writable?(@cache_path) then
-            puts "no valid work path: #{@work_path}" ; # no reason to exit
+            puts "no valid cache path: #{@cache_path}" ; # no reason to exit
         end
         @last_action = Time.now
         report("watching path #{@work_path}") if @verbose
@@ -302,7 +303,7 @@ class Watch < Monitor
                                             lck = File.expand_path(sessionfile.sub(/ses$/,'lck'))
                                             start_of_run = Time.now
                                             start_of_job = start_of_run.dup
-                                            max_runtime = @max_age
+                                            max_time = @max_age
                                             begin
                                                 start_of_job = vars['starttime'].to_i || start_of_run
                                                 start_of_job = start_of_run if start_of_job == 0
@@ -356,7 +357,11 @@ class Watch < Monitor
                                 else
                                     report("watchdog: skipping - id (#{vars['id']}) / status (#{vars['status']})") if @verbose
                                 end
-                                @skips[sessionfile] = true
+                                if @onlyonerun then
+                                    @skips[sessionfile] = true
+                                else
+                                    @skips.delete(sessionfile)
+                                end
                             else
                                 # not yet ok
                             end
@@ -379,6 +384,15 @@ class Watch < Monitor
         begin
             # report(Time.now.to_s) if @verbose
             loop do
+                @threads.delete_if do |k,v|
+                    begin
+                        v == nil || v.stop?
+                    rescue
+                        true
+                    else
+                        false
+                    end
+                end
                 if @threads.length == @max_threads then
                     if @delay > @max_threads then
                         sleep(@delay)
diff --git a/scripts/context/ruby/xmltools.rb b/scripts/context/ruby/xmltools.rb
index a10d34314..fe4fbde22 100644
--- a/scripts/context/ruby/xmltools.rb
+++ b/scripts/context/ruby/xmltools.rb
@@ -17,11 +17,7 @@
 
 banner = ['XMLTools', 'version 1.2.0', '2002/2006', 'PRAGMA ADE/POD']
 
-unless defined? ownpath
-    ownpath = $0.sub(/[\\\/][a-z0-9\-]*?\.rb/i,'')
-    # ownpath = File.dirname($0)
-    $: << ownpath
-end
+$: << File.expand_path(File.dirname($0)) ; $: << File.join($:.last,'lib') ; $:.uniq!
 
 require 'base/switch'
 require 'base/logger'
@@ -106,6 +102,11 @@ class Commands
                         output.xputs("<type>#{bt}</type>\n", 6)
                     end
                     output.xputs("<size>#{File.stat(f).size}</size>\n", 6)
+                    permissions = ''
+                    permissions << 'r' if File.readable?(f)
+                    permissions << 'w' if File.writable?(f)
+                    permissions << 'x' if File.executable?(f)
+                    output.xputs("<permissions>#{permissions}</permissions>\n", 6) unless permissions.empty?
                 end
                 output.xputs("<date>#{File.stat(f).mtime.strftime("%Y-%m-%d %H:%M")}</date>\n", 6)
                 output.xputs("</file>\n", 4)
diff --git a/scripts/context/stubs/mswin/luatools.bat b/scripts/context/stubs/mswin/luatools.bat
new file mode 100755
index 000000000..707657fad
--- /dev/null
+++ b/scripts/context/stubs/mswin/luatools.bat
@@ -0,0 +1,2 @@
+@echo off
+texmfstart luatools.lua %*
diff --git a/scripts/context/stubs/mswin/mtxtools.bat b/scripts/context/stubs/mswin/mtxtools.bat
new file mode 100755
index 000000000..b658116a5
--- /dev/null
+++ b/scripts/context/stubs/mswin/mtxtools.bat
@@ -0,0 +1,2 @@
+@echo off
+texmfstart mtxtools.rb %*
diff --git a/scripts/context/stubs/unix/luatools b/scripts/context/stubs/unix/luatools
new file mode 100755
index 000000000..cb3ec1add
--- /dev/null
+++ b/scripts/context/stubs/unix/luatools
@@ -0,0 +1,2 @@
+#!/bin/sh
+texmfstart luatools.lua "$@"
diff --git a/scripts/context/stubs/unix/mtxtools b/scripts/context/stubs/unix/mtxtools
new file mode 100755
index 000000000..2922e0b46
--- /dev/null
+++ b/scripts/context/stubs/unix/mtxtools
@@ -0,0 +1,2 @@
+#!/bin/sh
+texmfstart mtxtools.rb "$@"
-- 
cgit v1.2.3