1 # gaf.netlist - gEDA Netlist Extraction and Generation
2 # Copyright (C) 1998-2010 Ales Hvezda
3 # Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
4 # Copyright (C) 2013-2020 Roland Lutz
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software Foundation,
18 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # Copyright (C) 2011 Peter Brett <peter@peter-b.co.uk>
22 ## \file util_getopt.py
23 ## gnetlist `-O' command-line option parsing for backends.
25 # This module provides the function \ref backend_getopt to assist
26 # backends which wish to provide command-line gnetlist options via the
27 # `-O' argument. `backend_getopt' accepts a grammar and the set of
28 # `-O' arguments, and extracts the options.
30 # The name of an `-O' option is assumed to be all characters in the
31 # argument up to the first `=' or ` '.
33 import collections
, sys
35 ## Raised by \ref backend_getopt if it finds a problem with the arguments.
37 class OptionError(Exception):
40 NO_ARGUMENT
, REQUIRED_ARGUMENT
, OPTIONAL_ARGUMENT
= xrange(3)
42 Option
= collections
.namedtuple(
43 'Option', ['required', 'argument', 'predicate'])
45 ## Parse command-line `-O' arguments against a given backend option grammar.
47 # The \a grammar argument is expected to be a dictionary of this form:
49 # { 'option-name': Option(False, NO_ARGUMENT, None), ... }
51 # For each option, the following properties are given:
54 # If \a required is \c True, the option is required. \ref
55 # backend_getopt will raise an error if it is not found in the
59 # If \a value is REQUIRED_ARGUMENT, the option requires a value;
60 # if it is NO_ARGUMENT, it does not; and if it is
61 # OPTIONAL_ARGUMENT, the option may appear in the arguments with
64 # predicate (function)
65 # If the option accepts a value (i.e. you specified
66 # REQUIRED_ARGUMENT or OPTIONAL_ARGUMENT for this option), then
67 # \ref backend_getopt will apply \a predicate to the value and
68 # raise an error if it returns \c False. \a predicate should be a
69 # procedure which accepts a string and returns a boolean value.
71 # \returns a dictionary whose keys are the names of the backend
72 # options specified by the user and whose values are the
73 # option values, or \c True where the option was given but
76 # \throws OptionError if it finds a problem with the arguments
78 def backend_getopt(args
, grammar
, raise_exception
= False):
81 raise OptionError
, msg
82 sys
.stderr
.write(msg
+ "\n")
87 # First pass: process options
89 # Find the first index of a ' ' or '=' in the argument
91 i
= next(i
for i
, ch
in enumerate(arg
) if ch
in ' =')
94 name
, value
= arg
, None
97 error("Invalid backend option syntax '%s'" % arg
)
98 name
, value
= arg
[:i
], arg
[i
+ 1:]
103 # Is this a valid argument?
104 error("Unrecognized backend option '%s'" % name
)
106 # Validate the given `-O' argument name and value against the grammar.
108 # Check that a value was provided, if one was required, or vice versa.
109 if spec
.argument
== NO_ARGUMENT
and value
is not None:
110 error("Backend option '%s' doesn't allow an argument" % name
)
111 if spec
.argument
== REQUIRED_ARGUMENT
and value
is None:
112 error("Backend option '%s' requires an argument" % name
)
114 # If a value-verification predicate was provided, use it to verify
116 if spec
.predicate
is not None and value
is not None \
117 and not spec
.predicate(value
):
118 error("Invalid argument '%s' to backend option '%s'"
121 # If a value was provided, return it, otherwise return True.
125 options
[name
] = value
127 # Second pass: ensure required options have been provided
129 if grammar
[name
].required
and not name
in options
:
130 error("Backend option '%s' must be specified" % name
)