// OpenSTA, Static Timing Analyzer
// Copyright (c) 2026, Parallax Software, Inc.
//
// 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
// 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 .
//
// 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.
#include "ParseBus.hh"
#include
#include
#include "StringUtil.hh"
namespace sta {
bool
isBusName(std::string_view name,
const char brkt_left,
const char brkt_right,
char escape)
{
size_t len = name.size();
// Shortest bus name is a[0].
if (len >= 4
// Escaped bus brackets are not buses.
&& name[len - 2] != escape
&& name[len - 1] == brkt_right) {
size_t left = name.rfind(brkt_left);
return left != std::string_view::npos;
}
else
return false;
}
void
parseBusName(std::string_view name,
const char brkt_left,
const char brkt_right,
const char escape,
// Return values.
bool &is_bus,
std::string &bus_name,
int &index)
{
parseBusName(name, std::string_view(&brkt_left, 1),
std::string_view(&brkt_right, 1), escape,
is_bus, bus_name, index);
}
void
parseBusName(std::string_view name,
std::string_view brkts_left,
std::string_view brkts_right,
char escape,
// Return values.
bool &is_bus,
std::string &bus_name,
int &index)
{
is_bus = false;
size_t len = name.size();
// Shortest bus name is a[0].
if (len >= 4
// Escaped bus brackets are not buses.
&& name[len - 2] != escape) {
char last_ch = name[len - 1];
size_t brkt_index = brkts_right.find(last_ch);
if (brkt_index != std::string_view::npos) {
char brkt_left_ch = brkts_left[brkt_index];
size_t left = name.rfind(brkt_left_ch);
if (left != std::string_view::npos) {
is_bus = true;
bus_name.append(name.data(), left);
// Simple bus subscript.
index = std::stoi(std::string(name.substr(left + 1)));
}
}
}
}
void
parseBusName(std::string_view name,
const char brkt_left,
const char brkt_right,
char escape,
// Return values.
bool &is_bus,
bool &is_range,
std::string &bus_name,
int &from,
int &to,
bool &subscript_wild)
{
parseBusName(name, std::string_view(&brkt_left, 1),
std::string_view(&brkt_right, 1), escape,
is_bus, is_range, bus_name, from, to, subscript_wild);
}
void
parseBusName(std::string_view name,
std::string_view brkts_left,
std::string_view brkts_right,
char escape,
// Return values.
bool &is_bus,
bool &is_range,
std::string &bus_name,
int &from,
int &to,
bool &subscript_wild)
{
is_bus = false;
is_range = false;
subscript_wild = false;
size_t len = name.size();
// Shortest bus is a[0].
if (len >= 4
// Escaped bus brackets are not buses.
&& name[len - 2] != escape) {
char last_ch = name[len - 1];
size_t brkt_index = brkts_right.find(last_ch);
if (brkt_index != std::string_view::npos) {
char brkt_left_ch = brkts_left[brkt_index];
size_t left = name.rfind(brkt_left_ch);
if (left != std::string_view::npos) {
is_bus = true;
bus_name.append(name.data(), left);
// Check for bus range.
size_t range = name.find(':', left);
if (range != std::string_view::npos) {
is_range = true;
from = std::stoi(std::string(name.substr(left + 1)));
to = std::stoi(std::string(name.substr(range + 1)));
}
else {
if (left + 1 < len && name[left + 1] == '*')
subscript_wild = true;
else
from = to = std::stoi(std::string(name.substr(left + 1)));
}
}
}
}
}
std::string
escapeChars(std::string_view token,
const char ch1,
const char ch2,
const char escape)
{
std::string escaped;
escaped.reserve(token.size());
for (size_t i = 0; i < token.size(); i++) {
char ch = token[i];
if (ch == escape) {
if (i + 1 < token.size()) {
escaped += ch;
escaped += token[i + 1];
i++;
}
else
escaped += ch;
}
else if (ch == ch1 || ch == ch2) {
escaped += escape;
escaped += ch;
}
else
escaped += ch;
}
return escaped;
}
} // namespace