OpenSTA/util/PatternMatch.cc

222 lines
4.7 KiB
C++
Raw Normal View History

2018-09-28 17:54:21 +02:00
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
//
// This program 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 3 of the License, or
// (at your option) any later version.
//
// This program 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
2018-09-28 17:54:21 +02:00
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
2018-09-28 17:54:21 +02:00
2020-04-05 23:53:44 +02:00
#include "PatternMatch.hh"
#include <cstring>
2018-09-28 17:54:21 +02:00
#include <tcl.h>
2020-04-05 20:35:51 +02:00
2018-09-28 17:54:21 +02:00
namespace sta {
using std::string;
PatternMatch::PatternMatch(const char *pattern,
bool is_regexp,
bool nocase,
Tcl_Interp *interp) :
pattern_(pattern),
is_regexp_(is_regexp),
nocase_(nocase),
interp_(interp),
2019-03-13 01:25:53 +01:00
regexp_(nullptr)
2018-09-28 17:54:21 +02:00
{
if (is_regexp_)
compileRegexp();
}
PatternMatch::PatternMatch(const char *pattern) :
pattern_(pattern),
is_regexp_(false),
nocase_(false),
2019-03-13 01:25:53 +01:00
interp_(nullptr),
regexp_(nullptr)
2018-09-28 17:54:21 +02:00
{
}
PatternMatch::PatternMatch(const char *pattern,
const PatternMatch *inherit_from) :
pattern_(pattern),
is_regexp_(inherit_from->is_regexp_),
nocase_(inherit_from->nocase_),
interp_(inherit_from->interp_),
2019-03-13 01:25:53 +01:00
regexp_(nullptr)
2018-09-28 17:54:21 +02:00
{
if (is_regexp_)
compileRegexp();
}
PatternMatch::PatternMatch(const string &pattern,
rm tmp string uses commit 2d0a4f8e9a8b46faa2ba91e1be636c3c3ad95a7f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 21:25:37 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5514910a91707d615bac0bbed3a29f579eca8de2 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 18:21:54 2023 -0700 foo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 076a51d5816444e883232933c2ded7309291d0bc Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 16:38:42 2023 -0700 parse bus string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2b80e563cbbb6563a6b716431f391bbb6639f816 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 15:57:05 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9e4f2308658232d0b1ee9efcd948bb19ae5dd30f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 14:37:35 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ebad3afd49b08e7194452dd082c3c7c05767f875 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:59:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69647913932312a04ca06e7a04cca17ed50d4daf Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 55e67996a7b0651dbb5ee06cb89fe0410648c3c1 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:42:43 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 73cee43925c0d32940989c616440b4da18640121 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:55:17 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eba6d1413b8d87a64a90141e5263a56eede1df51 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:40:16 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 95d6ed78144512a37fd7c1d3d8a62fc4c8965818 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 08:18:46 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit faf82464d7be7fd6c958a21d401fa48ece4ac341 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:49:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cfc9064496cb6f46ec562b104bc7fff2fbc1b32e Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:37:12 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 057933a6ac356a7541883aa64b5109c7a0e8b8d1 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit fdeb6436a72413356a627dd1de1d8cec7fca4c4a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 19:53:44 2023 -0700 rm TmpString uses Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2023-03-26 15:34:36 +02:00
const PatternMatch *inherit_from) :
pattern_(pattern.c_str()),
is_regexp_(inherit_from->is_regexp_),
nocase_(inherit_from->nocase_),
interp_(inherit_from->interp_),
regexp_(nullptr)
{
if (is_regexp_)
compileRegexp();
}
2018-09-28 17:54:21 +02:00
void
PatternMatch::compileRegexp()
{
int flags = TCL_REG_ADVANCED;
if (nocase_)
flags |= TCL_REG_NOCASE;
string anchored_pattern;
anchored_pattern += '^';
anchored_pattern += pattern_;
anchored_pattern += '$';
Tcl_Obj *pattern_obj = Tcl_NewStringObj(anchored_pattern.c_str(),
anchored_pattern.size());
regexp_ = Tcl_GetRegExpFromObj(interp_, pattern_obj, flags);
2019-03-13 01:25:53 +01:00
if (regexp_ == nullptr && interp_)
2018-09-28 17:54:21 +02:00
throw RegexpCompileError(pattern_);
}
static bool
regexpWildcards(const char *pattern)
{
2019-03-13 01:25:53 +01:00
return strpbrk(pattern, ".+*?[]") != nullptr;
2018-09-28 17:54:21 +02:00
}
bool
PatternMatch::hasWildcards() const
{
if (is_regexp_)
return regexpWildcards(pattern_);
else
return patternWildcards(pattern_);
}
rm tmp string uses commit 2d0a4f8e9a8b46faa2ba91e1be636c3c3ad95a7f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 21:25:37 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5514910a91707d615bac0bbed3a29f579eca8de2 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 18:21:54 2023 -0700 foo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 076a51d5816444e883232933c2ded7309291d0bc Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 16:38:42 2023 -0700 parse bus string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2b80e563cbbb6563a6b716431f391bbb6639f816 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 15:57:05 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9e4f2308658232d0b1ee9efcd948bb19ae5dd30f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 14:37:35 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ebad3afd49b08e7194452dd082c3c7c05767f875 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:59:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69647913932312a04ca06e7a04cca17ed50d4daf Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 55e67996a7b0651dbb5ee06cb89fe0410648c3c1 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:42:43 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 73cee43925c0d32940989c616440b4da18640121 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:55:17 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eba6d1413b8d87a64a90141e5263a56eede1df51 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:40:16 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 95d6ed78144512a37fd7c1d3d8a62fc4c8965818 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 08:18:46 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit faf82464d7be7fd6c958a21d401fa48ece4ac341 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:49:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cfc9064496cb6f46ec562b104bc7fff2fbc1b32e Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:37:12 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 057933a6ac356a7541883aa64b5109c7a0e8b8d1 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit fdeb6436a72413356a627dd1de1d8cec7fca4c4a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 19:53:44 2023 -0700 rm TmpString uses Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2023-03-26 15:34:36 +02:00
bool
PatternMatch::match(const string &str) const
{
return match(str.c_str());
}
2018-09-28 17:54:21 +02:00
bool
PatternMatch::match(const char *str) const
{
if (regexp_)
2019-03-13 01:25:53 +01:00
return Tcl_RegExpExec(nullptr, regexp_, str, str) == 1;
2018-09-28 17:54:21 +02:00
else
return patternMatch(pattern_, str);
}
bool
PatternMatch::matchNoCase(const char *str) const
{
if (regexp_)
return Tcl_RegExpExec(0, regexp_, str, str) == 1;
else
return patternMatchNoCase(pattern_, str, nocase_);
}
////////////////////////////////////////////////////////////////
RegexpCompileError::RegexpCompileError(const char *pattern) :
2020-02-16 02:10:24 +01:00
Exception()
2018-09-28 17:54:21 +02:00
{
2020-04-07 07:19:50 +02:00
error_ = "TCL failed to compile regular expression '";
error_ += pattern;
2020-04-07 07:33:06 +02:00
error_ += "'.";
2018-09-28 17:54:21 +02:00
}
const char *
2020-02-16 02:10:24 +01:00
RegexpCompileError::what() const noexcept
2018-09-28 17:54:21 +02:00
{
2020-04-07 07:19:50 +02:00
return error_.c_str();
2018-09-28 17:54:21 +02:00
}
////////////////////////////////////////////////////////////////
bool
patternMatch(const char *pattern,
const char *str)
{
const char *p = pattern;
const char *s = str;
while (*p && *s && (*s == *p || *p == '?')) {
p++;
s++;
}
if (*p == '\0' && *s == '\0')
return true;
else if (*p == '*') {
if (p[1] == '\0')
return true;
while (*s) {
if (patternMatch(p + 1, s))
return true;
s++;
}
}
return false;
}
inline
bool equalCase(char s,
char p,
bool nocase)
{
return nocase
? tolower(s) == tolower(p)
: s == p;
}
bool
patternMatchNoCase(const char *pattern,
const char *str,
bool nocase)
{
const char *p = pattern;
const char *s = str;
while (*p && *s && (equalCase(*s, *p, nocase) || *p == '?')) {
p++;
s++;
}
if (*p == '\0' && *s == '\0')
return true;
else if (*p == '*') {
if (p[1] == '\0')
return true;
while (*s) {
if (patternMatchNoCase(p + 1, s, nocase))
return true;
s++;
}
}
return false;
}
bool
patternWildcards(const char *pattern)
{
return strpbrk(pattern, "*?") != 0;
}
} // namespace