Check-in [1471135306]
Overview
Comment:Initial dir2c.tcl
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:1471135306d89a99df16e67272acce5ac859a171
User & Date: rkeene on 2010-09-26 04:50:58
Other Links: manifest | tags
Context
2010-09-26
04:51
Fixed typo in matchindir

Added missing seek check-in: f44cf7fbe1 user: rkeene tags: trunk

04:50
Initial dir2c.tcl check-in: 1471135306 user: rkeene tags: trunk
04:50
Removed partial symlink implementation from KitDLL

Reorganized KitDLL code check-in: a9fb6a2bd7 user: rkeene tags: trunk

Changes

Added kitdll/buildsrc/kitdll-0.0/dir2c.tcl version [ce5afd32b3].

            1  +#! /usr/bin/env tclsh
            2  +
            3  +if {[llength $argv] != 2} {
            4  +	puts stderr "Usage: dir2c <hashkey> <startdir>"
            5  +
            6  +	exit 1
            7  +}
            8  +
            9  +set hashkey [lindex $argv 0]
           10  +set startdir [lindex $argv 1]
           11  +
           12  +proc shorten_file {dir file} {
           13  +	set dirNameLen [string length $dir]
           14  +
           15  +	if {[string range $file 0 [expr {$dirNameLen - 1}]] == $dir} {
           16  +		set file [string range $file $dirNameLen end]
           17  +	}
           18  +
           19  +	if {[string index $file 0] == "/"} {
           20  +		set file [string range $file 1 end]
           21  +	}
           22  +	return $file
           23  +}
           24  +
           25  +proc recursive_glob {dir} {
           26  +	set children [glob -nocomplain -directory $dir *]
           27  +
           28  +	set ret [list]
           29  +	foreach child $children {
           30  +		unset -nocomplain childinfo
           31  +		catch {
           32  +			file stat $child childinfo
           33  +		}
           34  +
           35  +		if {![info exists childinfo(type)]} {
           36  +			continue
           37  +		}
           38  +
           39  +		if {$childinfo(type) == "directory"} {
           40  +			foreach add [recursive_glob $child] {
           41  +				lappend ret $add
           42  +			}
           43  +
           44  +			lappend ret $child
           45  +
           46  +			continue
           47  +		}
           48  +
           49  +		if {$childinfo(type) != "file"} {
           50  +			continue
           51  +		}
           52  +
           53  +		lappend ret $child
           54  +	}
           55  +
           56  +	return $ret
           57  +}
           58  +
           59  +proc dir2c_hash {path} {
           60  +	set h 0
           61  +	set g 0
           62  +
           63  +	for {set idx 0} {$idx < [string length $path]} {incr idx} {
           64  +		binary scan [string index $path $idx] H* char
           65  +		set char "0x$char"
           66  +
           67  +		set h [expr {($h << 4) + $char}]
           68  +		set g [expr {$h & 0xf0000000}]
           69  +		if {$g != 0} {
           70  +			set h [expr {($h & 0xffffffff) ^ ($g >> 24)}]
           71  +		}
           72  +
           73  +		set h [expr {$h & ((~$g) & 0xffffffff)}]
           74  +	}
           75  +
           76  +	return $h
           77  +}
           78  +
           79  +proc stringify {data} {
           80  +	set ret "\""
           81  +	for {set idx 0} {$idx < [string length $data]} {incr idx} {
           82  +		binary scan [string index $data $idx] H* char
           83  +
           84  +		append ret "\\x${char}"
           85  +
           86  +		if {($idx % 20) == 0 && $idx != 0} {
           87  +			append ret "\"\n\""
           88  +		}
           89  +	}
           90  +
           91  +	set ret [string trim $ret "\n\""]
           92  +
           93  +	set ret "\"$ret\""
           94  +
           95  +	return $ret
           96  +}
           97  +
           98  +set files [recursive_glob $startdir]
           99  +
          100  +set cpp_tag "DIR2C_[string toupper $hashkey]"
          101  +set code_tag "dir2c_[string tolower $hashkey]"
          102  +
          103  +puts "#ifndef $cpp_tag"
          104  +puts "#  define $cpp_tag 1"
          105  +puts {#  include <unistd.h>
          106  +
          107  +#  ifndef LOADED_DIR2C_COMMON
          108  +#    define LOADED_DIR2C_COMMON 1
          109  +
          110  +typedef enum {
          111  +	DIR2C_FILETYPE_FILE,
          112  +	DIR2C_FILETYPE_DIR
          113  +} dir2c_filetype_t;
          114  +
          115  +struct dir2c_data {
          116  +	const char            *name;
          117  +	unsigned long         index;
          118  +	unsigned long         size;
          119  +	dir2c_filetype_t      type;
          120  +	const unsigned char   *data;
          121  +};
          122  +
          123  +static unsigned long dir2c_hash(const unsigned char *path) {
          124  +	unsigned long i, h = 0, g = 0;
          125  +
          126  +	for (i = 0; path[i]; i++) {
          127  +		h = (h << 4) + path[i];
          128  +		g = h & 0xf0000000;
          129  +		if (g) {
          130  +			h ^= (g >> 24);
          131  +		}
          132  +		h &= ((~g) & 0xffffffffLU);
          133  +	}
          134  +        
          135  +        return(h);
          136  +}
          137  +
          138  +#  endif /* !LOADED_DIR2C_COMMON */}
          139  +puts ""
          140  +
          141  +puts "static struct dir2c_data ${code_tag}_data\[\] = {"
          142  +puts "\t{"
          143  +puts "\t\t.name  = NULL,"
          144  +puts "\t\t.index = 0,"
          145  +puts "\t\t.type  = 0,"
          146  +puts "\t\t.size  = 0,"
          147  +puts "\t\t.data  = NULL,"
          148  +puts "\t},"
          149  +puts "\t{"
          150  +puts "\t\t.name  = \"\","
          151  +puts "\t\t.index = 1,"
          152  +puts "\t\t.type  = DIR2C_FILETYPE_DIR,"
          153  +puts "\t\t.size  = 0,"
          154  +puts "\t\t.data  = NULL,"
          155  +puts "\t},"
          156  +for {set idx 0} {$idx < [llength $files]} {incr idx} {
          157  +	set file [lindex $files $idx]
          158  +	set shortfile [shorten_file $startdir $file]
          159  +
          160  +	unset -nocomplain finfo type
          161  +	file stat $file finfo
          162  +
          163  +	switch -- $finfo(type) {
          164  +		"file" {
          165  +			set type "DIR2C_FILETYPE_FILE"
          166  +			set size $finfo(size)
          167  +
          168  +			set fd [open $file]
          169  +			fconfigure $fd -translation binary
          170  +			set data [read $fd]
          171  +			close $fd
          172  +
          173  +			set data [stringify $data]
          174  +		}
          175  +		"directory" {
          176  +			set type "DIR2C_FILETYPE_DIR"
          177  +			set data "NULL"
          178  +			set size 0
          179  +		}
          180  +	}
          181  +
          182  +	puts "\t{"
          183  +	puts "\t\t.name  = \"$shortfile\","
          184  +	puts "\t\t.index = [expr $idx + 2],"
          185  +	puts "\t\t.type  = $type,"
          186  +	puts "\t\t.size  = $size,"
          187  +	puts "\t\t.data  = $data,"
          188  +	puts "\t},"
          189  +}
          190  +puts "};"
          191  +puts ""
          192  +
          193  +puts "static unsigned long ${code_tag}_lookup_index(const char *path) {"
          194  +puts "\tswitch (dir2c_hash(path)) {"
          195  +puts "\t\tcase [dir2c_hash {}]:"
          196  +puts "\t\t\treturn(1);"
          197  +
          198  +set seenhashes [list]
          199  +for {set idx 0} {$idx < [llength $files]} {incr idx} {
          200  +	set file [lindex $files $idx]
          201  +	set shortfile [shorten_file $startdir $file]
          202  +	set hash [dir2c_hash $shortfile]
          203  +
          204  +	if {[lsearch -exact $seenhashes $hash] != -1} {
          205  +		puts stderr "ERROR: Duplicate hash seen: $file ($hash), aborting"
          206  +
          207  +		exit 1
          208  +	}
          209  +
          210  +	lappend seenhashes $hash
          211  +
          212  +	puts "\t\tcase $hash:"
          213  +	puts "\t\t\treturn([expr $idx + 2]);"
          214  +}
          215  +
          216  +puts "\t}"
          217  +puts "\treturn(0);"
          218  +puts "}"
          219  +puts ""
          220  +
          221  +puts "static struct dir2c_data *${code_tag}_getData(const char *path) {"
          222  +puts "\tunsigned long index;"
          223  +puts ""
          224  +puts "\tindex = ${code_tag}_lookup_index(path);"
          225  +puts "\tif (index == 0) {"
          226  +puts "\t\treturn(NULL);"
          227  +puts "\t}"
          228  +puts ""
          229  +puts "\treturn(&${code_tag}_data\[index\]);"
          230  +puts "}"
          231  +puts ""
          232  +
          233  +puts "#endif /* !$cpp_tag */"