Annotation For lib/xvfs/xvfs.tcl

Origin for each line in lib/xvfs/xvfs.tcl from check-in 09e53d3c38:

47dcf5fc27 2019-05-01    1: #! /usr/bin/env tclsh
47dcf5fc27 2019-05-01    2: 
47dcf5fc27 2019-05-01    3: namespace eval ::xvfs {}
47dcf5fc27 2019-05-01    4: 
2b7fa3a8fa 2019-09-20    5: set ::xvfs::_xvfsDir [file dirname [info script]]
2b7fa3a8fa 2019-09-20    6: 
47dcf5fc27 2019-05-01    7: # Functions
0bdbe4333e 2019-09-20    8: proc ::xvfs::_emitLine {line} {
12383d30b7 2019-09-20    9: 	if {[info command ::minirivet::_emitOutput] ne ""} {
12383d30b7 2019-09-20   10: 		::minirivet::_emitOutput "${line}\n"
12383d30b7 2019-09-20   11: 	} else {
12383d30b7 2019-09-20   12: 		puts $line
12383d30b7 2019-09-20   13: 	}
0bdbe4333e 2019-09-20   14: }
0bdbe4333e 2019-09-20   15: 
47dcf5fc27 2019-05-01   16: proc ::xvfs::printHelp {channel {errors ""}} {
47dcf5fc27 2019-05-01   17: 	if {[llength $errors] != 0} {
47dcf5fc27 2019-05-01   18: 		foreach error $errors {
702c74c153 2019-09-20   19: 			puts $channel "error: $error"
47dcf5fc27 2019-05-01   20: 		}
702c74c153 2019-09-20   21: 		puts $channel ""
47dcf5fc27 2019-05-01   22: 	}
702c74c153 2019-09-20   23: 	puts $channel "Usage: dir2c \[--help\] \[--output <filename>\] --directory <rootDirectory> --name <fsName>"
47dcf5fc27 2019-05-01   24: 	flush $channel
47dcf5fc27 2019-05-01   25: }
47dcf5fc27 2019-05-01   26: 
47dcf5fc27 2019-05-01   27: proc ::xvfs::sanitizeCString {string} {
47dcf5fc27 2019-05-01   28: 	set output [join [lmap char [split $string ""] {
47dcf5fc27 2019-05-01   29: 		if {![regexp {[A-Za-z0-9./-]} $char]} {
47dcf5fc27 2019-05-01   30: 			binary scan $char H* char
47dcf5fc27 2019-05-01   31: 			set char "\\[format %03o 0x$char]"
47dcf5fc27 2019-05-01   32: 		}
47dcf5fc27 2019-05-01   33: 
47dcf5fc27 2019-05-01   34: 		set char
47dcf5fc27 2019-05-01   35: 	}] ""]
47dcf5fc27 2019-05-01   36: 
47dcf5fc27 2019-05-01   37: 	return $output
47dcf5fc27 2019-05-01   38: }
47dcf5fc27 2019-05-01   39: 
32b55a907b 2019-05-02   40: proc ::xvfs::sanitizeCStringList {list {prefix ""} {width 80}} {
32b55a907b 2019-05-02   41: 	set lines [list]
32b55a907b 2019-05-02   42: 	set row [list]
32b55a907b 2019-05-02   43: 	foreach item $list {
32b55a907b 2019-05-02   44: 		lappend row "\"[sanitizeCString $item]\""
32b55a907b 2019-05-02   45: 		
32b55a907b 2019-05-02   46: 		set rowString [join $row {, }]
32b55a907b 2019-05-02   47: 		set rowString "${prefix}${rowString}"
32b55a907b 2019-05-02   48: 		if {[string length $rowString] > $width} {
32b55a907b 2019-05-02   49: 			set row [list]
32b55a907b 2019-05-02   50: 			lappend lines $rowString
32b55a907b 2019-05-02   51: 			unset rowString
32b55a907b 2019-05-02   52: 		}
32b55a907b 2019-05-02   53: 	}
32b55a907b 2019-05-02   54: 	if {[info exists rowString]} {
32b55a907b 2019-05-02   55: 		lappend lines $rowString
32b55a907b 2019-05-02   56: 	}
32b55a907b 2019-05-02   57: 	
32b55a907b 2019-05-02   58: 	return [join $lines "\n"]
32b55a907b 2019-05-02   59: }
32b55a907b 2019-05-02   60: 
47dcf5fc27 2019-05-01   61: proc ::xvfs::binaryToCHex {binary {prefix ""} {width 10}} {
2176e9cacf 2019-09-18   62: 	set binary [binary encode hex $binary]
47dcf5fc27 2019-05-01   63: 	set output [list]
47dcf5fc27 2019-05-01   64: 
47dcf5fc27 2019-05-01   65: 	set width [expr {$width * 2}]
47dcf5fc27 2019-05-01   66: 	set stopAt [expr {$width - 1}]
47dcf5fc27 2019-05-01   67: 
2176e9cacf 2019-09-18   68: 	set offset 0
2176e9cacf 2019-09-18   69: 	while 1 {
2176e9cacf 2019-09-18   70: 		set row [string range $binary $offset [expr {$offset + $stopAt}]]
2176e9cacf 2019-09-18   71: 		if {[string length $row] == 0} {
2176e9cacf 2019-09-18   72: 			break
2176e9cacf 2019-09-18   73: 		}
2176e9cacf 2019-09-18   74: 		incr offset [string length $row]
47dcf5fc27 2019-05-01   75: 
47dcf5fc27 2019-05-01   76: 		set rowOutput [list]
47dcf5fc27 2019-05-01   77: 		while {$row ne ""} {
47dcf5fc27 2019-05-01   78: 			set value [string range $row 0 1]
47dcf5fc27 2019-05-01   79: 			set row [string range $row 2 end]
47dcf5fc27 2019-05-01   80: 
47dcf5fc27 2019-05-01   81: 			lappend rowOutput "\\x$value"
47dcf5fc27 2019-05-01   82: 		}
47dcf5fc27 2019-05-01   83: 		set rowOutput [join $rowOutput {}]
47dcf5fc27 2019-05-01   84: 		set rowOutput "${prefix}\"${rowOutput}\""
47dcf5fc27 2019-05-01   85: 		lappend output $rowOutput
47dcf5fc27 2019-05-01   86: 	}
47dcf5fc27 2019-05-01   87: 
47dcf5fc27 2019-05-01   88: 	if {[llength $output] == 0} {
47dcf5fc27 2019-05-01   89: 		return "${prefix}\"\""
47dcf5fc27 2019-05-01   90: 	}
47dcf5fc27 2019-05-01   91: 
47dcf5fc27 2019-05-01   92: 	set output [join $output "\n"]
47dcf5fc27 2019-05-01   93: }
47dcf5fc27 2019-05-01   94: 
47dcf5fc27 2019-05-01   95: proc ::xvfs::processFile {fsName inputFile outputFile fileInfoDict} {
47dcf5fc27 2019-05-01   96: 	array set fileInfo $fileInfoDict
47dcf5fc27 2019-05-01   97: 
47dcf5fc27 2019-05-01   98: 	switch -exact -- $fileInfo(type) {
47dcf5fc27 2019-05-01   99: 		"file" {
47dcf5fc27 2019-05-01  100: 			set type "XVFS_FILE_TYPE_REG"
47dcf5fc27 2019-05-01  101: 			set fd [open $inputFile]
47dcf5fc27 2019-05-01  102: 			fconfigure $fd -encoding binary -translation binary -blocking true
47dcf5fc27 2019-05-01  103: 			set data [read $fd]
47dcf5fc27 2019-05-01  104: 			set size [string length $data]
47dcf5fc27 2019-05-01  105: 			set data [string trimleft [binaryToCHex $data "\t\t\t"]]
47dcf5fc27 2019-05-01  106: 			close $fd
47dcf5fc27 2019-05-01  107: 		}
47dcf5fc27 2019-05-01  108: 		"directory" {
47dcf5fc27 2019-05-01  109: 			set type "XVFS_FILE_TYPE_DIR"
32b55a907b 2019-05-02  110: 			set children $fileInfo(children)
32b55a907b 2019-05-02  111: 			set size [llength $children]
32b55a907b 2019-05-02  112: 			
32b55a907b 2019-05-02  113: 			if {$size == 0} {
32b55a907b 2019-05-02  114: 				set children "NULL"
32b55a907b 2019-05-02  115: 			} else {
32b55a907b 2019-05-02  116: 				set children [string trimleft [sanitizeCStringList $children "\t\t\t"]]
32b55a907b 2019-05-02  117: 				# This initializes it using a C99 compound literal, C99 is required
32b55a907b 2019-05-02  118: 				set children "(const char *\[\]) \{$children\}"
32b55a907b 2019-05-02  119: 			}
47dcf5fc27 2019-05-01  120: 		}
47dcf5fc27 2019-05-01  121: 		default {
47dcf5fc27 2019-05-01  122: 			return -code error "Unable to process $inputFile, unknown type: $fileInfo(type)"
47dcf5fc27 2019-05-01  123: 		}
47dcf5fc27 2019-05-01  124: 	}
47dcf5fc27 2019-05-01  125: 
0bdbe4333e 2019-09-20  126: 	::xvfs::_emitLine "\t\{"
0bdbe4333e 2019-09-20  127: 	::xvfs::_emitLine "\t\t.name = \"[sanitizeCString $outputFile]\","
0bdbe4333e 2019-09-20  128: 	::xvfs::_emitLine "\t\t.type = $type,"
0bdbe4333e 2019-09-20  129: 	::xvfs::_emitLine "\t\t.size = $size,"
32b55a907b 2019-05-02  130: 	switch -exact -- $fileInfo(type) {
32b55a907b 2019-05-02  131: 		"file" {
0bdbe4333e 2019-09-20  132: 			::xvfs::_emitLine "\t\t.data.fileContents = (const unsigned char *) $data"
32b55a907b 2019-05-02  133: 		}
32b55a907b 2019-05-02  134: 		"directory" {
0bdbe4333e 2019-09-20  135: 			::xvfs::_emitLine "\t\t.data.dirChildren  = $children"
32b55a907b 2019-05-02  136: 		}
32b55a907b 2019-05-02  137: 	}
0bdbe4333e 2019-09-20  138: 	::xvfs::_emitLine "\t\},"
47dcf5fc27 2019-05-01  139: }
47dcf5fc27 2019-05-01  140: 
47dcf5fc27 2019-05-01  141: proc ::xvfs::processDirectory {fsName directory {subDirectory ""}} {
47dcf5fc27 2019-05-01  142: 	set subDirectories [list]
47dcf5fc27 2019-05-01  143: 	set outputFiles [list]
47dcf5fc27 2019-05-01  144: 	set workingDirectory [file join $directory $subDirectory]
47dcf5fc27 2019-05-01  145: 	set outputDirectory $subDirectory
47dcf5fc27 2019-05-01  146: 
47dcf5fc27 2019-05-01  147: 	if {$subDirectory eq ""} {
47dcf5fc27 2019-05-01  148: 		set isTopLevel true
47dcf5fc27 2019-05-01  149: 	} else {
47dcf5fc27 2019-05-01  150: 		set isTopLevel false
47dcf5fc27 2019-05-01  151: 	}
47dcf5fc27 2019-05-01  152: 
47dcf5fc27 2019-05-01  153: 	if {$isTopLevel} {
0bdbe4333e 2019-09-20  154: 		::xvfs::_emitLine "static const struct xvfs_file_data xvfs_${fsName}_data\[\] = \{"
47dcf5fc27 2019-05-01  155: 	}
47dcf5fc27 2019-05-01  156: 
47dcf5fc27 2019-05-01  157: 	# XXX:TODO: Include hidden files ?
32b55a907b 2019-05-02  158: 	set children [list]
47dcf5fc27 2019-05-01  159: 	foreach file [glob -nocomplain -tails -directory $workingDirectory *] {
47dcf5fc27 2019-05-01  160: 		if {$file in {. ..}} {
47dcf5fc27 2019-05-01  161: 			continue
47dcf5fc27 2019-05-01  162: 		}
47dcf5fc27 2019-05-01  163: 
47dcf5fc27 2019-05-01  164: 		set inputFile [file join $workingDirectory $file]
d99958bdd3 2019-05-03  165: 		set outputFile [file join $outputDirectory [encoding convertto utf-8 $file]]
47dcf5fc27 2019-05-01  166: 
47dcf5fc27 2019-05-01  167: 		unset -nocomplain fileInfo
47dcf5fc27 2019-05-01  168: 		catch {
47dcf5fc27 2019-05-01  169: 			file lstat $inputFile fileInfo
47dcf5fc27 2019-05-01  170: 		}
47dcf5fc27 2019-05-01  171: 		if {![info exists fileInfo]} {
0bdbe4333e 2019-09-20  172: 			::xvfs::_emitLine stderr "warning: Unable to access $inputFile, skipping"
47dcf5fc27 2019-05-01  173: 		}
32b55a907b 2019-05-02  174: 		
32b55a907b 2019-05-02  175: 		lappend children [file tail $file]
47dcf5fc27 2019-05-01  176: 
47dcf5fc27 2019-05-01  177: 		if {$fileInfo(type) eq "directory"} {
47dcf5fc27 2019-05-01  178: 			lappend subDirectories $outputFile
32b55a907b 2019-05-02  179: 			continue
47dcf5fc27 2019-05-01  180: 		}
47dcf5fc27 2019-05-01  181: 
47dcf5fc27 2019-05-01  182: 		processFile $fsName $inputFile $outputFile [array get fileInfo]
47dcf5fc27 2019-05-01  183: 		lappend outputFiles $outputFile
47dcf5fc27 2019-05-01  184: 	}
47dcf5fc27 2019-05-01  185: 
47dcf5fc27 2019-05-01  186: 	foreach subDirectory $subDirectories {
47dcf5fc27 2019-05-01  187: 		lappend outputFiles {*}[processDirectory $fsName $directory $subDirectory]
47dcf5fc27 2019-05-01  188: 	}
32b55a907b 2019-05-02  189: 	
32b55a907b 2019-05-02  190: 	set inputFile $directory
32b55a907b 2019-05-02  191: 	set outputFile $outputDirectory
32b55a907b 2019-05-02  192: 	unset -nocomplain fileInfo
32b55a907b 2019-05-02  193: 	file stat $inputFile fileInfo
32b55a907b 2019-05-02  194: 	set fileInfo(children) $children
32b55a907b 2019-05-02  195: 
32b55a907b 2019-05-02  196: 	processFile $fsName $inputFile $outputFile [array get fileInfo]
32b55a907b 2019-05-02  197: 	lappend outputFiles $outputFile
47dcf5fc27 2019-05-01  198: 
47dcf5fc27 2019-05-01  199: 	if {$isTopLevel} {
0bdbe4333e 2019-09-20  200: 		::xvfs::_emitLine "\};"
47dcf5fc27 2019-05-01  201: 	}
47dcf5fc27 2019-05-01  202: 
47dcf5fc27 2019-05-01  203: 	return $outputFiles
47dcf5fc27 2019-05-01  204: }
47dcf5fc27 2019-05-01  205: 
47dcf5fc27 2019-05-01  206: proc ::xvfs::main {argv} {
47dcf5fc27 2019-05-01  207: 	# Main entry point
47dcf5fc27 2019-05-01  208: 	## 1. Parse arguments
47dcf5fc27 2019-05-01  209: 	if {[llength $argv] % 2 != 0} {
47dcf5fc27 2019-05-01  210: 		lappend argv ""
47dcf5fc27 2019-05-01  211: 	}
47dcf5fc27 2019-05-01  212: 
47dcf5fc27 2019-05-01  213: 	foreach {arg val} $argv {
47dcf5fc27 2019-05-01  214: 		switch -exact -- $arg {
47dcf5fc27 2019-05-01  215: 			"--help" {
47dcf5fc27 2019-05-01  216: 				printHelp stdout
47dcf5fc27 2019-05-01  217: 				exit 0
47dcf5fc27 2019-05-01  218: 			}
47dcf5fc27 2019-05-01  219: 			"--directory" {
47dcf5fc27 2019-05-01  220: 				set rootDirectory $val
47dcf5fc27 2019-05-01  221: 			}
47dcf5fc27 2019-05-01  222: 			"--name" {
47dcf5fc27 2019-05-01  223: 				set fsName $val
0bdbe4333e 2019-09-20  224: 			}
09e53d3c38 2019-09-20  225: 			"--output" - "--header" {
0bdbe4333e 2019-09-20  226: 				# Ignored, handled as part of some other process
32b55a907b 2019-05-02  227: 			}
47dcf5fc27 2019-05-01  228: 			default {
47dcf5fc27 2019-05-01  229: 				printHelp stderr [list "Invalid option: $arg $val"]
47dcf5fc27 2019-05-01  230: 				exit 1
47dcf5fc27 2019-05-01  231: 			}
47dcf5fc27 2019-05-01  232: 		}
47dcf5fc27 2019-05-01  233: 	}
47dcf5fc27 2019-05-01  234: 
47dcf5fc27 2019-05-01  235: 	## 2. Validate arguments
47dcf5fc27 2019-05-01  236: 	set errors [list]
47dcf5fc27 2019-05-01  237: 	if {![info exists rootDirectory]} {
47dcf5fc27 2019-05-01  238: 		lappend errors "--directory must be specified"
47dcf5fc27 2019-05-01  239: 	}
47dcf5fc27 2019-05-01  240: 	if {![info exists fsName]} {
47dcf5fc27 2019-05-01  241: 		lappend errors "--name must be specified"
47dcf5fc27 2019-05-01  242: 	}
47dcf5fc27 2019-05-01  243: 
47dcf5fc27 2019-05-01  244: 	if {[llength $errors] != 0} {
47dcf5fc27 2019-05-01  245: 		printHelp stderr $errors
47dcf5fc27 2019-05-01  246: 		exit 1
47dcf5fc27 2019-05-01  247: 	}
47dcf5fc27 2019-05-01  248: 
47dcf5fc27 2019-05-01  249: 	## 3. Start processing directory and producing initial output
32b55a907b 2019-05-02  250: 	set ::xvfs::outputFiles [processDirectory $fsName $rootDirectory]
47dcf5fc27 2019-05-01  251: 
47dcf5fc27 2019-05-01  252: 	set ::xvfs::fsName $fsName
47dcf5fc27 2019-05-01  253: 	set ::xvfs::rootDirectory $rootDirectory
2b7fa3a8fa 2019-09-20  254: }
2b7fa3a8fa 2019-09-20  255: 
3cb72a0d20 2019-09-20  256: proc ::xvfs::run {argv} {
d36db7c01b 2019-09-20  257: 	uplevel #0 { package require minirivet }
3cb72a0d20 2019-09-20  258: 
3cb72a0d20 2019-09-20  259: 	set ::xvfs::argv $argv
2b7fa3a8fa 2019-09-20  260: 	::minirivet::parse [file join $::xvfs::_xvfsDir xvfs.c.rvt]
2b7fa3a8fa 2019-09-20  261: }
2b7fa3a8fa 2019-09-20  262: 
d36db7c01b 2019-09-20  263: proc ::xvfs::setOutputChannel {channel} {
d36db7c01b 2019-09-20  264: 	uplevel #0 { package require minirivet }
d36db7c01b 2019-09-20  265: 	tailcall ::minirivet::setOutputChannel $channel
d36db7c01b 2019-09-20  266: }
d36db7c01b 2019-09-20  267: 
d36db7c01b 2019-09-20  268: proc ::xvfs::setOutputVariable {variable} {
d36db7c01b 2019-09-20  269: 	uplevel #0 { package require minirivet }
d36db7c01b 2019-09-20  270: 	tailcall ::minirivet::setOutputVariable $variable
09e53d3c38 2019-09-20  271: }
09e53d3c38 2019-09-20  272: 
09e53d3c38 2019-09-20  273: proc ::xvfs::staticIncludeHeaderData {headerData} {
09e53d3c38 2019-09-20  274: 	set ::xvfs::xvfsCoreH $headerData
09e53d3c38 2019-09-20  275: }
09e53d3c38 2019-09-20  276: 
09e53d3c38 2019-09-20  277: proc ::xvfs::staticIncludeHeader {pathToHeaderFile} {
09e53d3c38 2019-09-20  278: 	set fd [open $pathToHeaderFile]
09e53d3c38 2019-09-20  279: 	::xvfs::staticIncludeHeaderData [read $fd]
09e53d3c38 2019-09-20  280: 	close $fd
d36db7c01b 2019-09-20  281: }
47dcf5fc27 2019-05-01  282: 
47dcf5fc27 2019-05-01  283: package provide xvfs 1