@@ -24,10 +24,31 @@ set char }] ""] return $output } + +proc ::xvfs::sanitizeCStringList {list {prefix ""} {width 80}} { + set lines [list] + set row [list] + foreach item $list { + lappend row "\"[sanitizeCString $item]\"" + + set rowString [join $row {, }] + set rowString "${prefix}${rowString}" + if {[string length $rowString] > $width} { + set row [list] + lappend lines $rowString + unset rowString + } + } + if {[info exists rowString]} { + lappend lines $rowString + } + + return [join $lines "\n"] +} proc ::xvfs::binaryToCHex {binary {prefix ""} {width 10}} { binary scan $binary H* binary set output [list] @@ -69,13 +90,21 @@ set size [string length $data] set data [string trimleft [binaryToCHex $data "\t\t\t"]] close $fd } "directory" { - set data "NULL" set type "XVFS_FILE_TYPE_DIR" - set size "0" + set children $fileInfo(children) + set size [llength $children] + + if {$size == 0} { + set children "NULL" + } else { + set children [string trimleft [sanitizeCStringList $children "\t\t\t"]] + # This initializes it using a C99 compound literal, C99 is required + set children "(const char *\[\]) \{$children\}" + } } default { return -code error "Unable to process $inputFile, unknown type: $fileInfo(type)" } } @@ -82,11 +111,18 @@ puts "\t\{" puts "\t\t.name = \"[sanitizeCString $outputFile]\"," puts "\t\t.type = $type," puts "\t\t.size = $size," - puts "\t\t.data = (unsigned char *) $data" + switch -exact -- $fileInfo(type) { + "file" { + puts "\t\t.data.fileContents = (const unsigned char *) $data" + } + "directory" { + puts "\t\t.data.dirChildren = $children" + } + } puts "\t\}," } proc ::xvfs::processDirectory {fsName directory {subDirectory ""}} { set subDirectories [list] @@ -103,10 +139,11 @@ if {$isTopLevel} { puts "static struct xvfs_file_data xvfs_${fsName}_data\[\] = \{" } # XXX:TODO: Include hidden files ? + set children [list] foreach file [glob -nocomplain -tails -directory $workingDirectory *] { if {$file in {. ..}} { continue } @@ -118,34 +155,37 @@ file lstat $inputFile fileInfo } if {![info exists fileInfo]} { puts stderr "warning: Unable to access $inputFile, skipping" } + + lappend children [file tail $file] if {$fileInfo(type) eq "directory"} { lappend subDirectories $outputFile + continue } processFile $fsName $inputFile $outputFile [array get fileInfo] lappend outputFiles $outputFile } foreach subDirectory $subDirectories { lappend outputFiles {*}[processDirectory $fsName $directory $subDirectory] } + + set inputFile $directory + set outputFile $outputDirectory + unset -nocomplain fileInfo + file stat $inputFile fileInfo + set fileInfo(children) $children + + processFile $fsName $inputFile $outputFile [array get fileInfo] + lappend outputFiles $outputFile if {$isTopLevel} { puts "\};" - -if {0} { - puts "" - puts "static xvfs_${fsName}_nameToIndex\[\] = \{" - foreach outputFile $outputFiles { - puts "\t\"$outputFile\"," - } - puts "\};" -} } return $outputFiles } @@ -188,12 +228,12 @@ printHelp stderr $errors exit 1 } ## 3. Start processing directory and producing initial output - processDirectory $fsName $rootDirectory + set ::xvfs::outputFiles [processDirectory $fsName $rootDirectory] set ::xvfs::fsName $fsName set ::xvfs::rootDirectory $rootDirectory } package provide xvfs 1