From fed4b6f05c840be61413ee60cb4b1adf3ca5ed18 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Thu, 17 Feb 2005 15:01:51 +0000 Subject: [PATCH] * src/misc/optionmap.hh, src/misc/optionmap.cc (option_map::parse_options): Rewrite. Do not modify the input string, allow !foo as a shorthand for foo=0, and support K and M suffixes for values. * src/tgbatest/randtgba.cc (cons_emptiness_check): Simplify. * wrap/python/spot.i: Process optionmap.hh. * wrap/python/tests/optionmap.py: New file. * wrap/python/tests/Makefile.am (TESTS): Add it. --- ChangeLog | 11 ++++ src/misc/optionmap.cc | 101 ++++++++++++++++++++++++--------- src/misc/optionmap.hh | 9 ++- src/tgbatest/randtgba.cc | 16 +++--- wrap/python/spot.i | 4 +- wrap/python/tests/Makefile.am | 5 +- wrap/python/tests/optionmap.py | 64 +++++++++++++++++++++ 7 files changed, 170 insertions(+), 40 deletions(-) create mode 100755 wrap/python/tests/optionmap.py diff --git a/ChangeLog b/ChangeLog index edb14e13b..9cff3f881 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2005-02-17 Alexandre Duret-Lutz + + * src/misc/optionmap.hh, src/misc/optionmap.cc + (option_map::parse_options): Rewrite. Do not modify the input + string, allow !foo as a shorthand for foo=0, and support K and + M suffixes for values. + * src/tgbatest/randtgba.cc (cons_emptiness_check): Simplify. + * wrap/python/spot.i: Process optionmap.hh. + * wrap/python/tests/optionmap.py: New file. + * wrap/python/tests/Makefile.am (TESTS): Add it. + 2005-02-16 Alexandre Duret-Lutz * src/misc/optionmap.cc, src/misc/optionmap.hh (option_map::get, diff --git a/src/misc/optionmap.cc b/src/misc/optionmap.cc index a2430dc77..e4e81b377 100644 --- a/src/misc/optionmap.cc +++ b/src/misc/optionmap.cc @@ -25,40 +25,86 @@ namespace spot { - namespace - { - bool - to_int(const char* s, int &i) - { - char* endptr; - int res = strtol(s, &endptr, 10); - if (*endptr) - return false; - i = res; - return true; - } - }; - const char* - option_map::parse_options(char* options) + option_map::parse_options(const char* options) { - char* opt = strtok(options, ", \t;"); - while (opt) + while (*options) { - char* equal = strchr(opt, '='); - if (equal) + // Skip leading separators. + while (*options && strchr(" \t\n,;", *options)) + ++options; + + // `!foo' is a shorthand for `foo=0'. + const char* negated = 0; + if (*options == '!') { - *equal = 0; - int val; - if (!to_int(equal + 1, val)) - return opt; - options_[opt] = val; + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; + negated = options++; + } + + if (!*options) + { + if (negated) + return negated; + else + break; + } + + const char* name_start = options; + + // Find the end of the name. + while (*options && !strchr(", \t\n;=", *options)) + ++options; + + std::string name(name_start, options); + + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; + + if (*options != '=') + { + options_[name] = (negated ? 0 : 1); + } + else if (negated) + { + return negated; } else { - options_[opt] = 1; + ++options; + // Skip spaces. + while (*options && strchr(" \t\n", *options)) + ++options; + if (!*options) + return name_start; + + char* val_end; + int val = strtol(options, &val_end, 10); + if (val_end == options) + return name_start; + + if (*val_end == 'K') + { + val *= 1024; + ++val_end; + } + else if (*val_end == 'M') + { + val *= 1024 * 1024; + ++val_end; + } + else if (*val_end && !strchr(" \t\n,;", *val_end)) + { + return options; + } + + options = val_end; + + options_[name] = val; } - opt = strtok(0, ", \t;"); } return 0; } @@ -74,7 +120,8 @@ namespace spot return it->second; } - int option_map::operator[](const char* option) const + int + option_map::operator[](const char* option) const { return get(option); } diff --git a/src/misc/optionmap.hh b/src/misc/optionmap.hh index baa66d5f7..eb88c7e54 100644 --- a/src/misc/optionmap.hh +++ b/src/misc/optionmap.hh @@ -40,9 +40,16 @@ namespace spot /// can be optionnaly followed by an integer value (preceded by an equal /// sign). If not specified, the default value is 1. /// + /// The following three lines are equivalent. + /// \verbatim + /// optA !optB optC=4194304 + /// optA=1, optB=0, optC=4096K + /// optC = 4M; optA !optB + /// \endverbatim + /// /// \return A non-null pointer to the option for which an expected integer /// value cannot be parsed. - const char* parse_options(char* options); + const char* parse_options(const char* options); /// \brief Get the value of \a option. /// diff --git a/src/tgbatest/randtgba.cc b/src/tgbatest/randtgba.cc index 5caa006bb..b41f7cb19 100644 --- a/src/tgbatest/randtgba.cc +++ b/src/tgbatest/randtgba.cc @@ -104,17 +104,17 @@ struct ec_algo ec_algo ec_algos[] = { - { "Cou99", "poprem=0", + { "Cou99", "!poprem", couvreur99_cons, 0, -1U, true }, - { "Cou99_shy-", "poprem=0,shy=1,group=0", + { "Cou99_shy-", "!poprem shy !group", couvreur99_cons, 0, -1U, true }, - { "Cou99_shy", "poprem=0,shy=1,group=1", + { "Cou99_shy", "!poprem shy group", couvreur99_cons, 0, -1U, true }, - { "Cou99_rem", "poprem=1", + { "Cou99_rem", "poprem", couvreur99_cons, 0, -1U, true }, - { "Cou99_rem_shy-", "poprem=1,shy=1,group=0", + { "Cou99_rem_shy-", "poprem shy !group", couvreur99_cons, 0, -1U, true }, - { "Cou99_rem_shy", "poprem=1,shy=1,group=1", + { "Cou99_rem_shy", "poprem shy group", couvreur99_cons, 0, -1U, true }, { "CVWY90", 0, ms_cons, 0, 1, true }, @@ -141,11 +141,9 @@ cons_emptiness_check(int num, const spot::tgba* a, spot::option_map o = options; if (ec_algos[num].options) { - char* x = strdup(ec_algos[num].options); - const char* err = o.parse_options(x); + const char* err = o.parse_options(ec_algos[num].options); assert(!err); (void)err; - free(x); } if (n_acc < ec_algos[num].min_acc || n_acc > ec_algos[num].max_acc) a = degen; diff --git a/wrap/python/spot.i b/wrap/python/spot.i index f7317cd53..90c1ab909 100644 --- a/wrap/python/spot.i +++ b/wrap/python/spot.i @@ -1,4 +1,4 @@ -// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), +// Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre // et Marie Curie. // @@ -36,6 +36,7 @@ #include "misc/bddalloc.hh" #include "misc/minato.hh" #include "misc/modgray.hh" +#include "misc/optionmap.hh" #include "misc/random.hh" #include "ltlast/formula.hh" @@ -96,6 +97,7 @@ using namespace spot; %include "misc/version.hh" %include "misc/bddalloc.hh" %include "misc/minato.hh" +%include "misc/optionmap.hh" %include "misc/random.hh" %feature("director") spot::loopless_modular_mixed_radix_gray_code; diff --git a/wrap/python/tests/Makefile.am b/wrap/python/tests/Makefile.am index 23610c210..28ff34b4c 100644 --- a/wrap/python/tests/Makefile.am +++ b/wrap/python/tests/Makefile.am @@ -1,4 +1,4 @@ -## Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6), +## Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), ## département Systèmes Répartis Coopératifs (SRC), Université Pierre ## et Marie Curie. ## @@ -34,4 +34,5 @@ TESTS = \ ltl2tgba.test \ interdep.py \ minato.py \ - modgray.py + modgray.py \ + optionmap.py diff --git a/wrap/python/tests/optionmap.py b/wrap/python/tests/optionmap.py new file mode 100755 index 000000000..eaaabd01a --- /dev/null +++ b/wrap/python/tests/optionmap.py @@ -0,0 +1,64 @@ +# -*- mode: python; coding: iso-8859-1 -*- +# Copyright (C) 2005 Laboratoire d'Informatique de Paris 6 (LIP6), +# département Systèmes Répartis Coopératifs (SRC), Université Pierre +# et Marie Curie. +# +# This file is part of Spot, a model checking library. +# +# Spot 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. +# +# Spot 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 Spot; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +import ltihooks +import spot + +o = spot.option_map() +res = o.parse_options("optA, opta=2M, optb =4 ; optB = 7\ + , optC= 10") +assert not res + +assert o.get('optA') == 1 +assert o.get('opta') == 2*1024*1024 +assert o.get('optb') == 4 +assert o.get('optB') == 7 +assert o.get('optC') == 10 +assert o.get('none') == 0 +assert o.get('none', 16) == 16 + +o.set('optb', 40) +assert o.get('optb') == 40 + +res = o.parse_options("!optA !optb optC, !optB") +assert not res +assert o.get('optA') == 0 +assert o.get('opta') == 2*1024*1024 +assert o.get('optb') == 0 +assert o.get('optB') == 0 +assert o.get('optC') == 1 + +res = o.parse_options("!") +print res +assert res == "!" + +res = o.parse_options("foo, !opt = 1") +print res +assert res == "!opt = 1" + +res = o.parse_options("foo=3, opt == 1") +print res +assert res == "opt == 1" + +res = o.parse_options("foo=3opt == 1") +print res +assert res == "3opt == 1"