source: trunk/lang/tcl/scripts/getopts.tcl @ 6506

Last change on this file since 6506 was 3177, checked in by mmc, 12 years ago

Updated all of the copyright notices to reference the transfer to
the new HUBzero Foundation, LLC.

File size: 5.4 KB
Line 
1
2# ----------------------------------------------------------------------
3#  COMPONENT: getopts - simple argument parser
4#
5#  This utility makes it easy to process arguments for various
6#  commands.  You give a description of arguments, and it will
7#  parse and return the values.
8#
9#    getopts args params {
10#        value -foo foo_default
11#        flag group -bar default
12#        flag group -baz
13#    }
14#
15#  Note that both args and params are passed by name, not by
16#  value (not $args or $params).  This function initializes the
17#  params variable according to the values in the spec list.
18#  It then loops through all args, matching as many as possible
19#  from the list.  It throws an error on the first error
20#  encountered.  If there are extra arguments that don't match
21#  the flags and don't start with -, they are left in args, and
22#  processing stops.
23#
24# ======================================================================
25#  AUTHOR:  Michael McLennan, Purdue University
26#  Copyright (c) 2004-2012  HUBzero Foundation, LLC
27#
28#  See the file "license.terms" for information on usage and
29#  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
30# ======================================================================
31namespace eval Rappture { # forward declaration }
32
33# ----------------------------------------------------------------------
34# USAGE: getopts <listvar> <returnvar> <spec>
35#
36# Processes options in <listvar>, storing results in <returnvar>.
37# Throws an exception if an error is encountered.  Leaves any remaining
38# arguments (after flags) in <listvar>.
39# ----------------------------------------------------------------------
40proc Rappture::getopts {listVar returnVar spec} {
41    upvar $listVar args
42    upvar $returnVar params
43    catch {unset params}
44    set opts ""
45
46    #
47    # Pick apart the info in the <spec> and set up flags/params
48    #
49    foreach line [split $spec \n] {
50        if {[llength $line] == 0} {
51            continue  ;# ignore blank lines
52        }
53
54        set type [lindex $line 0]
55        switch -- $type {
56            value {
57                if {[llength $line] < 3} {
58                    error "bad value spec \"$line\": should be \"value -flag default\""
59                }
60                set name [lindex $line 1]
61                set flags($name) $type
62                set params($name) [lindex $line 2]
63                lappend opts $name
64            }
65            flag {
66                if {[llength $line] < 3 || [llength $line] > 4} {
67                    error "bad value spec \"$line\": should be \"flag group -flag ?default?\""
68                }
69                set group [lindex $line 1]
70                set name [lindex $line 2]
71                set flags($name) [list $type $group]
72                if {[llength $line] > 3} {
73                    set params($group) $name
74                    set params($name) 1
75                } else {
76                    if {![info exists params($group)]} {
77                        set params($group) ""
78                    }
79                    set params($name) 0
80                }
81                lappend opts $name
82            }
83            list {
84                if {[llength $line] < 3} {
85                    error "bad value spec \"$line\": should be \"list -flag default\""
86                }
87                set name [lindex $line 1]
88                set flags($name) $type
89                set params($name) [lindex $line 2]
90                lappend opts $name
91            }
92            default {
93                error "bad arg type \"$type\": should be flag or value"
94            }
95        }
96    }
97
98    #
99    # Now, walk through the values in $args and extract parameters.
100    #
101    while {[llength $args] > 0} {
102        set first [lindex $args 0]
103        if {[string index $first 0] != "-"} {
104            break
105        }
106        if {"--" == $first} {
107            set args [lrange $args 1 end]
108            break
109        }
110        if {![info exists params($first)]} {
111            error "bad option \"$first\": should be [join [lsort $opts] {, }]"
112        }
113        switch -- [lindex $flags($first) 0] {
114            value {
115                if {[llength $args] < 2} {
116                    error "missing value for option $first"
117                }
118                set params($first) [lindex $args 1]
119                set args [lrange $args 2 end]
120            }
121            flag {
122                set group [lindex $flags($first) 1]
123                set params($group) $first
124                set params($first) 1
125                set args [lrange $args 1 end]
126            }
127            list {
128                if {[llength $args] < 2} {
129                    error "missing value for option $first"
130                }
131                foreach arg [lrange $args 1 end] {
132                    if {[string index $arg 0] == "-"} {
133                        break
134                    }
135                }
136                set idx [lsearch -exact $args $arg]
137                if {$idx == [expr [llength $args] - 1]} {
138                    # reached the end of the $args list
139                    # with no other -'d arguments
140                    set params($first) [lrange $args 1 end]
141                    set args ""
142                } else {
143                    # there are further -'d arguments to process
144                    set params($first) [lrange $args 1 [expr $idx-1]]
145                    set args [lrange $args $idx end]
146                }
147            }
148        }
149    }
150    return ""
151}
Note: See TracBrowser for help on using the repository browser.