#! /usr/bin/tclsh
+###
+### Commander file inspector
+###
+### (c) 2003 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+###
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+###
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package require "elite" "1.0.1"
-if {[llength $argv] < 1} {
- puts stderr "usage: $argv0 \[-OPTION | ATTR | ATTR=VALUE\] ..."
- exit 1
+###--------------------------------------------------------------------------
+### Various type handlers.
+###
+### We associate a named type and some optional (type-specific) parameters
+### with each attribute in the commander file format. For each TYPE, there
+### are Tcl procedures:
+###
+### get/TYPE [PARAM ...] A -- return presentation form of the attribute A
+### dump/TYPE [PARAM ...] A -- return an external form of the attribute A
+### set/TYPE [PARAM ...] A V -- convert V from presentation form and store
+### as the attribute A
+
+proc dump-like-get {type} {
+ ## Define dump/TYPE as a synonym for get/TYPE.
+
+ proc dump/$type {args} [list uplevel 1 get/$type \$args]
}
-jameson cmdr
+## string -- just a plain unconverted string.
proc get/string {a} { global cmdr; return $cmdr($a) }
-proc dump/string {a} { global cmdr; return $cmdr($a) }
+dump-like-get string
proc set/string {a v} { global cmdr; set cmdr($a) $v }
+## int MIN MAX -- an integer constrained to lie between the stated
+## (inclusive) bounds.
proc get/int {min max a} {
global cmdr
return [format "%d" [expr {$cmdr($a) + 0}]]
}
-proc dump/int {min max a} {
- global cmdr
- return [format "%d" [expr {$cmdr($a) + 0}]]
-}
+dump-like-get int
proc set/int {min max a v} {
global cmdr
if {$v < $min || $v > $max} { error "value out of range" }
set cmdr($a) $v
}
+## tenth MIN MAX -- a numerical value constrained to lie between the stated
+## inclusive bounds; the internal format is an integer containing ten times
+## the presentation value.
proc get/tenth {min max a} {
global cmdr
return [format "%.1f" [expr {$cmdr($a)/10.0}]]
}
-proc dump/tenth {min max a} {
- global cmdr
- return [format "%.1f" [expr {$cmdr($a)/10.0}]]
-}
+dump-like-get tenth
proc set/tenth {min max a v} {
global cmdr
if {$v < $min || $v > $max} { error "value out of range" }
set cmdr($a) [expr {int($v * 10)}]
}
+## choice MIN MAX L -- the presentation form is either an integer between the
+## given inclusive bounds, or a token matching one of the items in the
+## list L; the internal form is the integer, or the index of the token
+## in the list.
proc get/choice {min max l a} {
global cmdr
set x "custom"
set cmdr($a) $v
}
+## seed -- a galaxy seed; any valid galaxy spec is permitted as the
+## presentation form.
proc get/seed {a} { global cmdr; return $cmdr($a) }
-proc dump/seed {a} { global cmdr; return $cmdr($a) }
+dump-like-get seed
proc set/seed {a v} {
global cmdr
set s [parse-galaxy-spec $v]
destructure [list . cmdr($a)] $s
}
+## world -- a planet identifier; on input, any planet spec is permitted
+## (relative to the commander's established galaxy), and on output a
+## summary description is produced.
proc get/world {a} {
global cmdr gov eco
set ww [elite-galaxylist $cmdr(gal-seed)]
set cmdr(world-y) [expr {$p(y)/2}]
}
+## bool DFL -- internal form is either zero or DFL; external form is one of a
+## number of standard boolean tokens.
proc get/bool {dfl a} {
global cmdr
if {$cmdr($a)} { return "yes" } else { return "no" }
}
-proc dump/bool {dfl a} {
- global cmdr
- if {$cmdr($a)} { return "yes" } else { return "no" }
-}
+dump-like-get bool
proc set/bool {dfl a v} {
global cmdr
switch -- [string tolower $v] {
- "y" - "yes" - "true" - "on" { set v 1 }
- "n" - "no" - "false" - "off" { set v 0 }
+ "y" - "yes" - "true" - "on" - "t" { set v 1 }
+ "n" - "no" - "false" - "off" - "nil" { set v 0 }
}
if {$v} { set cmdr($a) $dfl } else { set cmdr($a) 0 }
}
+## comment -- a pseudo-type for discarding commnts in input files.
proc set/comment {a v} { }
+###--------------------------------------------------------------------------
+### Attribute table.
+
+### The `attr' array maps commander attribute names to TYPE [PARAM ...]
+### lists; the `attrs' list contains the names in a canonical order.
set attrs {}
+
+## Comment magic.
set attr(\#) { comment }
+
+## Basic attributes.
foreach {a type} {
mission { int 0 255 }
score { choice 0 65535 {
set attr($a) $type
lappend attrs $a
}
+
+## Lasers.
foreach l {front rear left right} {
set attr($l-laser) {
choice 0 255
}
lappend attrs $l-laser
}
+
+## Standard boolean properties.
foreach i {
ecm fuel-scoop energy-bomb escape-pod docking-computer gal-hyperdrive
} {
set attr($i) { bool 255 }
lappend attrs $i
}
+
+## Station and hold produce.
foreach l {station hold} {
foreach {t p} $products {
set attr($l-$t) { int 0 255 }
}
}
+###--------------------------------------------------------------------------
+### Main program.
+
+jameson cmdr
+
+## Parse the command-line.
+if {[llength $argv] < 1} {
+ puts stderr "usage: $argv0 \[-OPTION | ATTR | ATTR=VALUE\] ..."
+ exit 1
+}
+
+proc show-attrs {pat} {
+ ## Show the attributes whose names match the glob pattern PAT. Return the
+ ## number of matches.
+
+ global attr attrs
+ set n 0
+ foreach a $attrs {
+ if {[string match $pat $a]} {
+ puts [format "%-20s %s" $a [eval \
+ get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
+ incr n
+ }
+ }
+ return $n
+}
+
+proc load-file {file} {
+ ## Load FILE as a commander.
+
+ global argv0 cmdr
+ if {[catch { elite-unpackcmdr cmdr [read-file $file] } err]} {
+ puts stderr "$argv0: couldn't read `$file': $err"
+ exit 1
+ }
+}
+
set acted 0
for {set i 0} {$i < [llength $argv]} {incr i} {
set a [lindex $argv $i]
switch -regexp -- $a {
- "^-reset$" { jameson cmdr }
+
+ "^-reset$" {
+ ## Reset the commander back to Jameson.
+
+ jameson cmdr
+ }
+
"^-show$" {
- foreach a $attrs {
- puts [format "%-20s %s" $a [eval \
- get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
- }
+ ## Produce a human-readable description of the commander.
+
+ show-attrs "*"
set acted 1
}
+
"^-load$" {
+ ## Load a commander file.
+
incr i
set a [lindex $argv $i]
- if {[catch { elite-unpackcmdr cmdr [read-file $a] } err]} {
- puts stderr "$argv0: couldn't read `$a': $err"
- exit 1
- }
+ load-file $a
}
+
"^-save$" {
+ ## Write the commander to a file.
+
incr i
set a [lindex $argv $i]
if {[catch { write-file $a [elite-packcmdr cmdr] } err]} {
}
set acted 1
}
+
"^-dump$" {
+ ## Dump a machine-readable textual description of the commander.
+
puts "# {Elite commander dump}"
puts ""
foreach a $attrs {
}
set acted 1
}
+
"^-read$" {
+ ## Read back a description produced by `-dump'.
+
incr i
set a [lindex $argv $i]
if {[catch {
exit 1
}
}
+
"^-" {
+ ## An unknown option.
+
puts stderr "$argv0: unknown option `$a'"
exit 1
}
+
"^[a-z][a-z-]*=" {
+ ## An assignment ATTR=VALUE.
+
regexp {^([a-z][a-z-]*)=(.*)$} $a . a v
if {![info exists attr($a)]} {
puts stderr "$argv0: no such attribute `$a'"
exit 1
}
}
+
default {
- set n 0
- foreach aa $attrs {
- if {[string match $a $aa]} {
- incr n
- puts [format "%-20s %s" $aa [eval \
- get/[lindex $attr($aa) 0] \
- [lrange $attr($aa) 1 end] [list $aa]]]
- }
- }
- if {$n} {
+ ## If the argument matches any attribute names, then print the matching
+ ## attributes; otherwise load the named file.
+
+ if {[show-attrs $a]} {
set acted 1
} else {
- if {[catch { elite-unpackcmdr cmdr [read-file $a] } err]} {
- puts stderr "$argv0: couldn't read `$a': $err"
- exit 1
- }
+ load-file $a
}
}
}
}
+
+## If we didn't do anything, write out a description of the file.
if {!$acted} {
- foreach a $attrs {
- puts [format "%-20s %s" $a [eval \
- get/[lindex $attr($a) 0] [lrange $attr($a) 1 end] [list $a]]]
- }
+ show-attrs "*"
}
+
+###----- That's all, folks --------------------------------------------------