1 # -*-mode: tcl; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
3 # $Id: Getopt.tcl,v 1.4 2004-10-13 12:08:57 vvzhy Exp $
5 ###### Getopt.tcl ######
6 ############################################################
7 # Netmath Copyright (C) 1998 William F. Schelter #
8 # For distribution under GNU public License. See COPYING. #
9 ############################################################
11 #####sample option list. Error will be signalled if "Required" option
14 # {xdot Required {specifies dx/dt = xdot. eg -xdot "x+y+sin(x)^2"} }
15 # {ydot Required {specifies dy/dt = ydot. eg -ydot "x-y^2+exp(x)"} }
16 # {xradius 10 "Width in x direction of the x values" }
17 # {yradius 10 "Height in y direction of the y values"}
22 #-----------------------------------------------------------------
24 # optLoc -- if $usearray is not 0, then the OPTION is stored
25 # in a hashtable, otherwise in the variable whose name is the
27 # Results: a form which when 'set' will allow storing value.
31 #----------------------------------------------------------------
33 proc optLoc
{ op ar
} {
34 # puts "$ar,[lindex $op 0]"
35 # puts "return=$ar\([lindex $op 0]\)"
39 #puts "$ar\([lindex $op 0]\)"
40 return "$ar\([lindex $op 0]\)"
47 #-----------------------------------------------------------------
49 # getOptions -- given OPTLIST a specification for the options taken,
50 # parse the alternating keyword1 value1 keyword2 value2 options_supplied
51 # to make sure they are allowed, and not just typos, and to supply defaults
52 # for ones not given. Give an error message listing options.
53 # a specification is { varname default_value "doc string" }
54 # and optlist, is a list of these. the key should be -varname
56 # -debug 1 "means print the values on standard out"
57 # -allowOtherKeys 1 "dont signal an error if -option is supplied but not in
59 # -usearray "should give a NAME, so that options are stored in NAME(OPTION)
60 # -setdefaults "if not 0 (default is 1) do `set OPTION dflt' for all options"
61 # If a key is specified twice eg. -key1 val1 -key1 val2, then the first
62 # value val1 will be used
65 # Side Effects: set the values in the callers environment
67 #----------------------------------------------------------------
70 proc getOptions
{ optlist options_supplied args
} {
71 # global getOptionSpecs
73 set ar
[assoc
-usearray $args 0]
74 set help
[assoc
-help $args ""]
75 if { "$ar" != "0" } { global $ar }
76 set debug
[assoc
-debug $args 0]
77 set allowOtherKeys
[assoc
-allowOtherKeys $args 0]
78 set setdefaults
[assoc
-setdefaults $args 1]
81 foreach {key val
} $options_supplied {
82 if { [info exists already
($key)] } { continue }
86 if { "$key" == "-[lindex $op 0]" } {
87 uplevel 1 set [optLoc
$op $ar] [list $val]
89 append supplied
" [lindex $op 0]"
96 if { $found == 0 && !$allowOtherKeys } {
97 catch {set caller
[lindex [info level
-1] 0]}
98 error [concat "`$caller'" [mc
"does not take the key"] "`$key':\n[optionHelpMessage $optlist]\n$help"]
102 foreach op
$optlist {
103 if { [lsearch $supplied [lindex $op 0]] < 0 } {
104 if { "[lindex $op 1]" == "Required" } {
105 catch {set caller
[lindex [info level
-1] 0]}
106 error [concat "`-[lindex $op 0]'" [mc
"is required option for"] "`$caller':\n[optionHelpMessage $optlist]"]
108 if { $setdefaults } {
110 uplevel 1 set [optLoc
$op $ar] [list [lindex $op 1]]
113 # for debugging see them.
114 # if { $debug } { uplevel 1 puts "[optLoc $op $ar]=\$[optLoc $op $ar]"}
115 if { $debug } { puts "[optLoc $op $ar]=[safeValue [optLoc $op $ar] 2]"}
120 proc getOptionDefault
{ key optionList
} {
121 foreach v
$optionList {
122 if { "[lindex $v 0]" == "$key" } { return [lindex $v 1]}
127 proc assq
{key
list {dflt
""}} {
128 foreach v
$list { if { "[lindex $v 0]" == "$key" } { return $v }}
132 proc safeValue
{ loc level
} {
133 if { ![catch { set me
[uplevel $level set $loc] } ] } {
142 proc optionFirstItems
{ lis
} {
144 foreach v
$lis { append ans
" [list [lindex $v 0]]" }
148 proc optionHelpMessage
{ optlist
} {
150 foreach op
$optlist {
152 " -[lindex $op 0] \[ [lindex $op 1] \] --[lindex $op 2]\n"
159 #-----------------------------------------------------------------
161 # setSplittingOptionsRest -- takes ARGLIST and splits it into
162 # two lists, the first part it stores in KEYPAIRS and the second in REST
168 # Side Effects: sets the variables in the local frame passed to KEYPAIRS
170 #----------------------------------------------------------------
172 proc setSplittingOptionsRest
{ keypairs rest arglist
} {
173 upvar 1 $keypairs keys
177 if { $i >= [llength $arglist] } { break }
178 if { "[string range [lindex $arglist $i] 0 0]" == "-" } {
184 set keys
[lrange $arglist 0 [expr $i -1]]
185 set res
[lrange $arglist $i end
]
190 ## endsource getopt.tcl