15470Snate@binkert.org# Copyright (c) 2005 The Regents of The University of Michigan
25470Snate@binkert.org# All rights reserved.
35470Snate@binkert.org#
45470Snate@binkert.org# Redistribution and use in source and binary forms, with or without
55470Snate@binkert.org# modification, are permitted provided that the following conditions are
65470Snate@binkert.org# met: redistributions of source code must retain the above copyright
75470Snate@binkert.org# notice, this list of conditions and the following disclaimer;
85470Snate@binkert.org# redistributions in binary form must reproduce the above copyright
95470Snate@binkert.org# notice, this list of conditions and the following disclaimer in the
105470Snate@binkert.org# documentation and/or other materials provided with the distribution;
115470Snate@binkert.org# neither the name of the copyright holders nor the names of its
125470Snate@binkert.org# contributors may be used to endorse or promote products derived from
135470Snate@binkert.org# this software without specific prior written permission.
145470Snate@binkert.org#
155470Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
165470Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
175470Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
185470Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
195470Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205470Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
215470Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
225470Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
235470Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
245470Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
255470Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265470Snate@binkert.org#
275470Snate@binkert.org# Authors: Nathan Binkert
285470Snate@binkert.org
2913714Sandreas.sandberg@arm.comfrom __future__ import print_function
3013714Sandreas.sandberg@arm.comfrom __future__ import absolute_import
3113714Sandreas.sandberg@arm.com
325470Snate@binkert.orgimport optparse
335470Snate@binkert.orgimport sys
345470Snate@binkert.org
355470Snate@binkert.orgfrom optparse import *
365470Snate@binkert.org
375470Snate@binkert.orgclass nodefault(object): pass
385470Snate@binkert.org
395470Snate@binkert.orgclass splitter(object):
405470Snate@binkert.org    def __init__(self, split):
415470Snate@binkert.org        self.split = split
425470Snate@binkert.org    def __call__(self, option, opt_str, value, parser):
435470Snate@binkert.org        values = value.split(self.split)
445470Snate@binkert.org        dest = getattr(parser.values, option.dest)
455470Snate@binkert.org        if dest is None:
465470Snate@binkert.org            setattr(parser.values, option.dest, values)
475470Snate@binkert.org        else:
485470Snate@binkert.org            dest.extend(values)
495470Snate@binkert.org
505586Snate@binkert.orgclass OptionParser(dict):
515470Snate@binkert.org    def __init__(self, *args, **kwargs):
525470Snate@binkert.org        kwargs.setdefault('formatter', optparse.TitledHelpFormatter())
535470Snate@binkert.org        self._optparse = optparse.OptionParser(*args, **kwargs)
545470Snate@binkert.org        self._optparse.disable_interspersed_args()
555470Snate@binkert.org
565470Snate@binkert.org        self._allopts = {}
575470Snate@binkert.org
585470Snate@binkert.org        # current option group
595470Snate@binkert.org        self._group = self._optparse
605470Snate@binkert.org
615586Snate@binkert.org    def set_defaults(self, *args, **kwargs):
625586Snate@binkert.org        return self._optparse.set_defaults(*args, **kwargs)
635586Snate@binkert.org
645470Snate@binkert.org    def set_group(self, *args, **kwargs):
655470Snate@binkert.org        '''set the current option group'''
665470Snate@binkert.org        if not args and not kwargs:
675470Snate@binkert.org            self._group = self._optparse
685470Snate@binkert.org        else:
695470Snate@binkert.org            self._group = self._optparse.add_option_group(*args, **kwargs)
705470Snate@binkert.org
715470Snate@binkert.org    def add_option(self, *args, **kwargs):
725470Snate@binkert.org        '''add an option to the current option group, or global none set'''
735470Snate@binkert.org
745470Snate@binkert.org        # if action=split, but allows the option arguments
755470Snate@binkert.org        # themselves to be lists separated by the split variable'''
765470Snate@binkert.org
775470Snate@binkert.org        if kwargs.get('action', None) == 'append' and 'split' in kwargs:
785470Snate@binkert.org            split = kwargs.pop('split')
795470Snate@binkert.org            kwargs['default'] = []
805470Snate@binkert.org            kwargs['type'] = 'string'
815470Snate@binkert.org            kwargs['action'] = 'callback'
825470Snate@binkert.org            kwargs['callback'] = splitter(split)
835470Snate@binkert.org
845470Snate@binkert.org        option = self._group.add_option(*args, **kwargs)
855470Snate@binkert.org        dest = option.dest
865470Snate@binkert.org        if dest not in self._allopts:
875470Snate@binkert.org            self._allopts[dest] = option
885470Snate@binkert.org
895470Snate@binkert.org        return option
905470Snate@binkert.org
915470Snate@binkert.org    def bool_option(self, name, default, help):
925470Snate@binkert.org        '''add a boolean option called --name and --no-name.
935470Snate@binkert.org        Display help depending on which is the default'''
945470Snate@binkert.org
955470Snate@binkert.org        tname = '--%s' % name
965470Snate@binkert.org        fname = '--no-%s' % name
975470Snate@binkert.org        dest = name.replace('-', '_')
985470Snate@binkert.org        if default:
995470Snate@binkert.org            thelp = optparse.SUPPRESS_HELP
1005470Snate@binkert.org            fhelp = help
1015470Snate@binkert.org        else:
1025470Snate@binkert.org            thelp = help
1035470Snate@binkert.org            fhelp = optparse.SUPPRESS_HELP
1045470Snate@binkert.org
1055470Snate@binkert.org        topt = self.add_option(tname, action="store_true", default=default,
1065470Snate@binkert.org                               help=thelp)
1075470Snate@binkert.org        fopt = self.add_option(fname, action="store_false", dest=dest,
1085470Snate@binkert.org                               help=fhelp)
1095470Snate@binkert.org
1105470Snate@binkert.org        return topt,fopt
1115470Snate@binkert.org
1125470Snate@binkert.org    def __getattr__(self, attr):
1135470Snate@binkert.org        if attr.startswith('_'):
1145586Snate@binkert.org            return super(OptionParser, self).__getattribute__(attr)
1155470Snate@binkert.org
1165586Snate@binkert.org        if attr in self:
1175586Snate@binkert.org            return self[attr]
1185470Snate@binkert.org
1195586Snate@binkert.org        return super(OptionParser, self).__getattribute__(attr)
1205470Snate@binkert.org
1215470Snate@binkert.org    def __setattr__(self, attr, value):
1225470Snate@binkert.org        if attr.startswith('_'):
1235586Snate@binkert.org            super(OptionParser, self).__setattr__(attr, value)
1245586Snate@binkert.org        elif attr in self._allopts:
1255586Snate@binkert.org            defaults = { attr : value }
1265586Snate@binkert.org            self.set_defaults(**defaults)
1275586Snate@binkert.org            if attr in self:
1285586Snate@binkert.org                self[attr] = value
1295586Snate@binkert.org        else:
1305586Snate@binkert.org            super(OptionParser, self).__setattr__(attr, value)
1315470Snate@binkert.org
1325470Snate@binkert.org    def parse_args(self):
1335470Snate@binkert.org        opts,args = self._optparse.parse_args()
1345470Snate@binkert.org
13513709Sandreas.sandberg@arm.com        for key,val in opts.__dict__.items():
1365586Snate@binkert.org            if val is not None or key not in self:
1375586Snate@binkert.org                self[key] = val
1385470Snate@binkert.org
1395470Snate@binkert.org        return args
1405470Snate@binkert.org
1415470Snate@binkert.org    def usage(self, exitcode=None):
1425470Snate@binkert.org        self._optparse.print_help()
1435470Snate@binkert.org        if exitcode is not None:
1445470Snate@binkert.org            sys.exit(exitcode)
1455470Snate@binkert.org
146