Index: build/pre.sh ================================================================== --- build/pre.sh +++ build/pre.sh @@ -11,8 +11,9 @@ autoconf; autoheader rm -rf autom4te.cache rm -f *~ ./configure || exit 1 + make mk4tcl.tcl.h make distclean ) || exit 1 Index: kitsh/buildsrc/kitsh-0.0/Makefile.in ================================================================== --- kitsh/buildsrc/kitsh-0.0/Makefile.in +++ kitsh/buildsrc/kitsh-0.0/Makefile.in @@ -9,16 +9,19 @@ all: kit kit: $(OBJS) $(ARCHS) $(CC) $(CPPFLAGS) $(CFLAGS) -o kit $(OBJS) $(ARCHS) $(LDFLAGS) $(LIBS) +mk4tcl.tcl.h: mk4tcl.tcl + ./stringify.tcl mk4tcl.tcl > mk4tcl.tcl.h + clean: rm -f kit $(OBJS) distclean: clean rm -f config.h Makefile config.log config.status rm -rf autom4te.cache mrproper: distclean - rm -f configure config.h + rm -f configure config.h mk4tcl.tcl.h .PHONY: all clean distclean Index: kitsh/buildsrc/kitsh-0.0/kitInit.c ================================================================== --- kitsh/buildsrc/kitsh-0.0/kitInit.c +++ kitsh/buildsrc/kitsh-0.0/kitInit.c @@ -76,11 +76,15 @@ "return -code $code $res\n" "}\n" #endif "proc tclKitInit {} {\n" "rename tclKitInit {}\n" +#ifdef KIT_INCLUDES_MK4TCL "catch { load {} Mk4tcl }\n" +#else +#include "mk4tcl.tcl.h" +#endif "mk::file open exe [info nameofexecutable] -readonly\n" "set n [mk::select exe.dirs!0.files name boot.tcl]\n" "if {$n != \"\"} {\n" "set s [mk::get exe.dirs!0.files!$n contents]\n" "if {![string length $s]} { error \"empty boot.tcl\" }\n" ADDED kitsh/buildsrc/kitsh-0.0/mk4tcl.tcl Index: kitsh/buildsrc/kitsh-0.0/mk4tcl.tcl ================================================================== --- kitsh/buildsrc/kitsh-0.0/mk4tcl.tcl +++ kitsh/buildsrc/kitsh-0.0/mk4tcl.tcl @@ -0,0 +1,831 @@ +#! /usr/bin/env tclsh +# ReadKit, a viewer/extractor/converter for starkits which does not +# require TclKit or MetaKit. This file was generated by "rkgen.tcl". +# +# June 2002, Jean-Claude Wippler + +# this is needed so often that I just drop copies of it all over the place +if {![info exists auto_index(lassign)] && [info commands lassign] == ""} { + set auto_index(lassign) { + proc lassign {l args} { + foreach v $l a $args { uplevel 1 [list set $a $v] } + } + } +} + +catch { + load {} zlib + package require zlib +} + +if {[info comm mmap] == ""} { + # mmap and mvec primitives in pure Tcl (a C version is present in critlib) + + namespace export mmap mvec + + namespace eval v { + array set mmap_data {} + array set mvec_shifts { + - -1 0 -1 + 1 0 2 1 4 2 8 3 + 16 4 16r 4 + 32 5 32r 5 32f 5 32fr 5 + 64 6 64r 6 64f 6 64fr 6 } + } + + proc mmap {fd args} { + upvar #0 v::mmap_data($fd) data + # special case if fd is the name of a variable (qualified or global) + if {[uplevel #0 [list info exists $fd]]} { + upvar #0 $fd var + set data $var + } + # cache a full copy of the file to simulate memory mapping + if {![info exists data]} { + set pos [tell $fd] + seek $fd 0 end + set end [tell $fd] + seek $fd 0 + set trans [fconfigure $fd -translation] + fconfigure $fd -translation binary + set data [read $fd $end] + fconfigure $fd -translation $trans + seek $fd $pos + } + set total [string length $data] + if {[llength $args] == 0} { + return $total + } + foreach {off len} $args break + if {$len < 0} { + set len $total + } + if {$len < 0 || $len > $total - $off} { + set len [expr {$total - $off}] + } + binary scan $data @${off}a$len s + return $s + } + + proc mvec {v args} { + foreach {mode data off len} $v break + if {[info exists v::mvec_shifts($mode)]} { + # use _mvec_get to access elements + set shift $v::mvec_shifts($mode) + if {[llength $v] < 4} { + set len $off + } + set get [list _mvec_get $shift $v *] + } else { + # virtual mode, set to evaluate script + set shift "" + set len [lindex $v end] + set get $v + } + # try to derive vector length from data length if not specified + if {$len == "" || $len < 0} { + set len 0 + if {$shift >= 0} { + if {[llength $v] < 4} { + set n [string length $data] + } else { + set n [mmap $data] + } + set len [expr {($n << 3) >> $shift}] + } + } + set nargs [llength $args] + # with just a varname as arg, return info about this vector + if {$nargs == 0} { + if {$shift == ""} { + return [list $len {} $v] + } + return [list $len $mode $shift] + } + foreach {pos count pred cond} $args break + # with an index as second arg, do a single access and return element + if {$nargs == 1} { + return [uplevel 1 [lreplace $get end end $pos]] + } + if {$count < 0} { + set count $len + } + if {$count > $len - $pos && $shift != -1} { + set count [expr {$len - $pos}] + } + if {$nargs == 4} { + upvar $pred x + } + set r {} + incr count $pos + # loop through specified range to build result vector + # with four args, used that as predicate function to filter + # with five args, use fourth as loop var and apply fifth as condition + for {set x $pos} {$x < $count} {incr x} { + set y [uplevel 1 [lreplace $get end end $x]] + switch $nargs { + 3 { + if {![uplevel 1 [list $pred $v $x $y]]} continue + } + 4 { + if {![uplevel 1 [list expr $cond]]} continue + } + } + lappend r $y + } + return $r + } + + proc _mvec_get {shift desc index} { + foreach {mode data off len} $desc break + switch -- $mode { + - { + return $index + } + 0 { + return $data + } + } + if {[llength $desc] < 4} { + set off [expr {($index << $shift) >> 3}] + } else { + # don't load more than 8 bytes from the proper offset + incr off [expr {($index << $shift) >> 3}] + set data [mmap $data $off 8] + set off 0 + } + switch -- $mode { + 1 { + binary scan $data @${off}c value + return [expr {($value>>($index&7)) &1}] + } + 2 { + binary scan $data @${off}c value + return [expr {($value>>(($index&3) <<1)) &3}] + } + 4 { + binary scan $data @${off}c value + return [expr {($value>>(($index&1) <<2)) &15}] + } + 8 { + set w 1 + set f c + } + 16 { + set w 2 + set f s + } + 16r { + set w 2 + set f S + } + 32 { + set w 4 + set f i + } + 32r { + set w 4 + set f I + } + 32fr - + 32f { + set w 4 + set f f + } + 64 - + 64r { + set w 8 + set f i2 + } + 64fr - + 64f { + set w 8 + set f d + } + } + + binary scan $data @$off$f value + return $value + } + + # vim: ft=tcl + +} + +if {[info comm dbopen] == ""} { + # Decoder for MetaKit datafiles in Tcl + + # requires mmap/mvec primitives: + #source [file join [info dirname [info script]] mvprim.tcl] + + namespace export dbopen dbclose dbtree access vnames vlen + + namespace eval v { + variable widths { + {8 16 1 32 2 4} + {4 8 1 16 2 0} + {2 4 8 1 0 16} + {2 4 0 8 1 0} + {1 2 4 0 8 0} + {1 2 4 0 0 8} + {1 2 0 4 0 0} } + } + + proc fetch {file} { + if {$file == ""} { + error "temp storages not supported" + } + set v::data [open $file] + set v::seqn 0 + } + + proc byte_seg {off len} { + incr off $v::zero + return [mmap $v::data $off $len] + } + + proc int_seg {off cnt} { + set vec [list 32r [byte_seg $off [expr {4*$cnt}]]] + return [mvec $vec 0 $cnt] + } + + proc get_s {len} { + set s [byte_seg $v::curr $len] + incr v::curr $len + return $s + } + + proc get_v {} { + set v 0 + while 1 { + set char [mvec $v::byte $v::curr] + incr v::curr + set v [expr {$v*128+($char&0xff)}] + if {$char < 0} { + return [incr v -128] + } + } + } + + proc get_p {rows vs vo} { + upvar $vs size $vo off + set off 0 + if {$rows == 0} { + set size 0 + } else { + set size [get_v] + if {$size > 0} { + set off [get_v] + } + } + } + + proc header {{end ""}} { + set v::zero 0 + if {$end == ""} { + set end [mmap $v::data] + } + set v::byte [list 8 $v::data $v::zero $end] + lassign [int_seg [expr {$end-16}] 4] t1 t2 t3 t4 + set v::zero [expr {$end-$t2-16}] + incr end -$v::zero + set v::byte [list 8 $v::data $v::zero $end] + lassign [int_seg 0 2] h1 h2 + lassign [int_seg [expr {$h2-8}] 2] e1 e2 + set v::info(mkend) $h2 + set v::info(mktoc) $e2 + set v::info(mklen) [expr {$e1 & 0xffffff}] + set v::curr $e2 + } + + proc layout {fmt} { + regsub -all { } $fmt "" fmt + regsub -all {(\w+)\[} $fmt "{\\1 {" fmt + regsub -all {\]} $fmt "}}" fmt + regsub -all {,} $fmt " " fmt + return $fmt + } + + proc descparse {desc} { + set names {} + set types {} + foreach x $desc { + if {[llength $x] == 1} { + lassign [split $x :] name type + if {$type == ""} { + set type S + } + } else { + lassign $x name type + } + lappend names $name + lappend types $type + } + return [list $names $types] + } + + proc numvec {rows type} { + get_p $rows size off + if {$size == 0} { + return {0 0} + } + set w [expr {int(($size<<3) /$rows)}] + if {$rows <= 7 && 0 < $size && $size <= 6} { + set w [lindex [lindex $v::widths [expr {$rows-1}]] [expr {$size-1}]] + } + if {$w == 0} { + error "numvec?" + } + switch $type\ + F { + set w 32f + }\ + D { + set w 64f + } + incr off $v::zero + return [list $w $v::data $off $rows] + } + + proc lazy_str {self rows type pos sizes msize moff index} { + set soff {} + for {set i 0} {$i < $rows} {incr i} { + set n [mvec $sizes $i] + lappend soff $pos + incr pos $n + } + if {$msize > 0} { + set slen [mvec $sizes 0 $rows] + set v::curr $moff + set limit [expr {$moff+$msize}] + for {set row 0} {$v::curr < $limit} {incr row} { + incr row [get_v] + get_p 1 ms mo + set soff [lreplace $soff $row $row $mo] + set slen [lreplace $slen $row $row $ms] + } + set sizes [list lindex $slen $rows] + } + if {$type == "S"} { + set adj -1 + } else { + set adj 0 + } + set v::node($self) [list get_str $soff $sizes $adj $rows] + return [mvec $v::node($self) $index] + } + + proc get_str {soff sizes adj index} { + set n [mvec $sizes $index] + return [byte_seg [lindex $soff $index] [incr n $adj]] + } + + proc lazy_sub {self desc size off rows index} { + set v::curr $off + lassign [descparse $desc] names types + set subs {} + for {set i 0} {$i < $rows} {incr i} { + if {[get_v] != 0} { + error "lazy_sub?" + } + lappend subs [prepare $types] + } + set v::node($self) [list get_sub $names $subs $rows] + return [mvec $v::node($self) $index] + } + +#proc backtrace {{level_adj 0}} { +# set ret [list] +# +# set level [expr 0 - $level_adj] +# for {set i [expr [info level] - $level_adj]} {$i > 1} {incr i -1} { +# incr level -1 +# set ret [linsert $ret 0 [lindex [info level $level] 0]] +# } +# set ret [linsert $ret 0 GLOBAL] +# +# return $ret +#} + + proc get_sub {names subs index} { +#puts stderr "DEBUG: get_sub: [list $names $subs $index]" +#puts "backtrace: [backtrace]" + lassign [lindex $subs $index] rows handlers + return [list get_view $names $rows $handlers $rows] + } + + proc prepare {types} { + set r [get_v] + set handlers {} + foreach x $types { + set n [incr v::seqn] + lappend handlers $n + switch $x { + I - + L - + F - + D { + set v::node($n) [numvec $r $x] + } + B - + S { + get_p $r size off + set sizes {0 0} + if {$size > 0} { + set sizes [numvec $r I] + } + get_p $r msize moff + set v::node($n) [list lazy_str $n $r $x $off $sizes\ + $msize $moff $r] + } + default { + get_p $r size off + set v::node($n) [list lazy_sub $n $x $size $off $r $r] + } + } + } + return [list $r $handlers] + } + + proc get_view {names rows handlers index} { + return [list get_prop $names $rows $handlers $index [llength $names]] + } + + proc get_prop {names rows handlers index ident} { + set col [lsearch -exact $names $ident] + if {$col < 0} { + error "unknown property: $ident" + } + set h [lindex $handlers $col] + set ret [mvec $v::node($h) $index] + + return $ret + } + + proc dbopen {db file} { + # open datafile, stores datafile descriptors and starts building tree + if {$db == ""} { + set r {} + foreach {k v} [array get v::dbs] { + lappend r $k [lindex $v 0] + } + return $r + } + fetch $file + header + if {[get_v] != 0} { + error "dbopen?" + } + set desc [layout [get_s [get_v]]] + lassign [descparse $desc] names types + set root [get_sub $names [list [prepare $types]] 0] + set v::dbs($db) [list $file $v::data $desc [mvec $root 0]] + return $db + } + + proc dbclose {db} { + # close datafile, get rid of stored info + unset v::dbs($db) + set v::data "" ;# it may be big + } + + proc dbtree {db} { + # datafile selection, first step in access navigation loop + return [lindex $v::dbs($db) 3] + } + + proc access {spec} { + # this is the main access navigation loop + set s [split $spec ".!"] + set x [list dbtree [array size v::dbs]] + foreach y $s { + set x [mvec $x $y] + } + return $x + } + + proc vnames {view} { + # return a list of property names + if {[lindex $view 0] != "get_view"} { + error "vnames?" + } + return [lindex $view 1] + } + + proc vlen {view} { + # return the number of rows in this view + if {[lindex $view 0] != "get_view"} { + error "vlen?" + } + return [lindex $view 2] + } + + # vim: ft=tcl + +} + +if {[info comm mk_file] == ""} { + # Compatibility layer for MetaKit + + # requires dbopen/dbclose/dbtree/access/vnames/vlen/mvec primitives + #source [file join [info dirname [info script]] decode.tcl] + + namespace export mk_* + + proc mk_file {cmd args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::file $cmd $args" + lassign $args db file + switch $cmd { + open { + return [dbopen $db $file] + } + close { + dbclose $db + } + views { + return [vnames [dbtree $db]] + } + commit { + + } + default { + error "mk_file $cmd?" + } + } + } + + proc mk_view {cmd path args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::view $cmd $path $args" + lassign $args a1 + switch $cmd { + info { + return [vnames [access $path]] + } + layout { + set layout "NOTYET" + if {[llength $args] > 0 && $layout != $a1} { + #error "view restructuring not supported" + } + return $layout + } + size { + set len [vlen [access $path]] + if {[llength $args] > 0 && $len != $a1} { + error "view resizing not supported" + } + return [vlen [access $path]] + } + default { + error "mk_view $cmd?" + } + } + } + + proc mk_cursor {cmd cursor args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::cursor $cmd $cursor $args" + upvar $cursor v + switch $cmd { + create { + NOTYET + } + incr { + NOTYET + } + pos - + position { + if {$args != ""} { + regsub {!-?\d+$} $v {} v + append v !$args + return $args + } + if {![regexp {\d+$} $v n]} { + set n -1 + } + return $n + } + default { + error "mk_cursor $cmd?" + } + } + } + + proc mk_get {path args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::get $path $args" + set rowref [access $path] + set sized 0 + if {[lindex $args 0] == "-size"} { + set sized 1 + set args [lrange $args 1 end] + } + set ids 0 + if {[llength $args] == 0} { + set args [vnames $rowref] + set ids 1 + } + set r {} + foreach x $args { + if {$ids} { + lappend r $x + } + set v [mvec $rowref $x] +if {[string range $v 0 8] == "get_view "} { +# XXX: ?!?!?: TODO: FIX +set v 1 +} + catch { + set v [zlib decompress $v] + } + if {$sized} { + lappend r [string length $v] + } else { + lappend r $v + } + } + if {[llength $args] == 1} { + set r [lindex $r 0] + } + + return $r + } + + proc mk_loop {cursor path args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::loop $cursor $path ..." + upvar $cursor v + if {[llength $args] == 0} { + set args [list $path] + set path $v + regsub {!-?\d+$} $path {} path + } + lassign $args a1 a2 a3 a4 + set rowref [access $path] + set first 0 + set limit [vlen $rowref] + set step 1 + switch [llength $args] { + 1 { + set body $a1 + } + 2 { + set first $a1 + set body $a2 + } + 3 { + set first $a1 + set limit $a2 + set body $a3 + } + 4 { + set first $a1 + set limit $a2 + set step $a3 + set body $a4 + } + default { + error "mk_loop arg count?" + } + } + set code 0 + for {set i $first} {$i < $limit} {incr i $step} { + set v $path!$i + set code [catch [list uplevel 1 $body] err] + switch $code { + 1 - + 2 { + return -code $code $err + } + 3 { + break + } + } + } + } + + proc mk_select {path args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::select $path $args" + # only handle the simplest case: exact matches + if {[lindex $args 0] == "-count"} { + set maxitems [lindex $args 1] + set args [lrange $args 2 end] + } + + set currmatchmode "caseinsensitive" + + set keys {} + set value {} + set matchmodes {} + for {set idx 0} {$idx < [llength $args]} {incr idx 2} { + switch -glob -- [lindex $args $idx] { + "-glob" { + set currmatchmode "glob" + incr idx -1 + continue + } + "-*" { + error "Unhandled option: [lindex $args $idx]" + } + } + + set k [lindex $args $idx] + set v [lindex $args [expr {$idx+1}]] + + lappend keys $k + lappend values $v + lappend matchmodes $currmatchmode + } + set r {} + mk_loop c $path { + set x [eval mk_get $c $keys] + set matchCnt 0 + for {set idx 0} {$idx < [llength $x]} {incr idx} { + set val [lindex $values $idx] + set chkval [lindex $x $idx] + set matchmode [lindex $matchmodes $idx] + + switch -- $matchmode { + "caseinsensitive" { + if {$val == $chkval} { + incr matchCnt + } + } + "glob" { + if {[string match $val $chkval]} { + incr matchCnt + } + } + } + + } + if {$matchCnt == [llength $keys]} { + lappend r [mk_cursor position c] + } + } + + if {[info exists maxitems]} { + set r [lrange $r 0 [expr $maxitems - 1]] + } + + return $r + } + + proc mk__rechan {path prop cmd chan args} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::_rechan $path $prop $cmd $chan $args" + + set key [list $path $prop] + if {![info exists ::mk__cache($key)]} { + set ::mk__cache($key) [mk::get $path $prop] + } + if {![info exists ::mk__offset($key)]} { + set ::mk__offset($key) 0 + } + set data $::mk__cache($key) + set offset $::mk__offset($key) + + switch -- $cmd { + "read" { + set count [lindex $args 0] + set retval [string range $data $offset [expr {$offset + $count - 1}]] + + set readbytes [string length $retval] + + incr offset $readbytes + } + "close" { + unset -nocomplain ::mk__cache($key) + unset -nocomplain ::mk__offset($key) + return + } + default { +#puts stderr "${indent}DEBUG: mk::_rechan: Called for cmd $cmd" + return -code error "Not implemented: cmd = $cmd" + } + } + + set ::mk__offset($key) $offset + + return $retval + } + + proc mk_channel {path prop {mode "r"}} { +#set indent [string repeat " " [info level]] +#puts stderr "${indent}DEBUG: mk::channel $path $prop $mode" + set fd [rechan [list mk__rechan $path $prop] 2] + + return $fd + } + # vim: ft=tcl + +} + +# set up the MetaKit compatibility definitions +foreach x {file view cursor get loop select channel} { + interp alias {} ::mk::$x {} ::mk_$x +} + +package provide Mk4tcl 2.4.0.1 ADDED kitsh/buildsrc/kitsh-0.0/stringify.tcl Index: kitsh/buildsrc/kitsh-0.0/stringify.tcl ================================================================== --- kitsh/buildsrc/kitsh-0.0/stringify.tcl +++ kitsh/buildsrc/kitsh-0.0/stringify.tcl @@ -0,0 +1,27 @@ +#! /usr/bin/env tclsh + +proc stringifyfile {filename {key 0}} { + catch { + set fd [open $filename r] + } + + if {![info exists fd]} { + return "" + } + + set data [read -nonewline $fd] + close $fd + + foreach line [split $data \n] { + set line [string map [list "\\" "\\\\" "\"" "\\\""] $line] + append ret " \"$line\\n\"\n" + } + + return $ret +} + +foreach file $argv { + puts [stringifyfile $file] +} + +exit 0 Index: mk4tcl/build.sh ================================================================== --- mk4tcl/build.sh +++ mk4tcl/build.sh @@ -68,12 +68,17 @@ export CPPFLAGS fi # Build static libraries for linking against Tclkit ./configure --disable-shared --prefix="${INSTDIR}" --exec-prefix="${INSTDIR}" --with-tcl="${TCLCONFIGDIR}/../generic" ${CONFIGUREEXTRA} - ${MAKE:-make} tcllibdir="${INSTDIR}/lib" AR="${AR:-ar}" RANLIB="${RANLIB:-ranlib}" || exit 1 - ${MAKE:-make} tcllibdir="${INSTDIR}/lib" AR="${AR:-ar}" RANLIB="${RANLIB:-ranlib}" install + ${MAKE:-make} tcllibdir="${INSTDIR}/lib" AR="${AR:-ar}" RANLIB="${RANLIB:-ranlib}" && \ + ${MAKE:-make} tcllibdir="${INSTDIR}/lib" AR="${AR:-ar}" RANLIB="${RANLIB:-ranlib}" install || ( + rm -rf "${INSTDIR}" + mkdir "${INSTDIR}" + + exit 1 + ) || exit 1 exit 0 ) || exit 1 exit 0