// OpenSTA, Static Timing Analyzer // Copyright (c) 2021, 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 . #include "ParseBus.hh" #include #include #include #include "StringUtil.hh" namespace sta { using std::string; bool isBusName(const char *name, const char brkt_left, const char brkt_right, char escape) { size_t len = strlen(name); // Shortest bus name is a[0]. if (len >= 4 // Escaped bus brackets are not buses. && name[len - 2] != escape && name[len - 1] == brkt_right) { const char *left = strrchr(name, brkt_left); return left != nullptr; } else return false; } void parseBusName(const char *name, const char brkt_left, const char brkt_right, char escape, // Return values. char *&bus_name, int &index) { const char brkts_left[2] = {brkt_left, '\0'}; const char brkts_right[2] = {brkt_right, '\0'}; parseBusName(name, brkts_left, brkts_right, escape, bus_name, index); } void parseBusName(const char *name, const char *brkts_left, const char *brkts_right, char escape, // Return values. char *&bus_name, int &index) { bus_name = nullptr; size_t len = strlen(name); // 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]; const char *brkt_right_ptr = strchr(brkts_right, last_ch); if (brkt_right_ptr) { size_t brkt_index = brkt_right_ptr - brkts_right; char brkt_left = brkts_left[brkt_index]; const char *left = strrchr(name, brkt_left); if (left) { size_t bus_name_len = left - name; bus_name = new char[bus_name_len + 1]; strncpy(bus_name, name, bus_name_len); bus_name[bus_name_len] = '\0'; // Simple bus subscript. index = atoi(left + 1); } } } } void parseBusRange(const char *name, const char brkt_left, const char brkt_right, char escape, // Return values. char *&bus_name, int &from, int &to) { const char brkts_left[2] = {brkt_left, '\0'}; const char brkts_right[2] = {brkt_right, '\0'}; parseBusRange(name, brkts_left, brkts_right, escape, bus_name, from, to); } void parseBusRange(const char *name, const char *brkts_left, const char *brkts_right, char escape, // Return values. char *&bus_name, int &from, int &to) { bus_name = nullptr; size_t len = strlen(name); // Shortest bus range is a[1:0]. if (len >= 6 // Escaped bus brackets are not buses. && name[len - 2] != escape) { char last_ch = name[len - 1]; const char *brkt_right_ptr = strchr(brkts_right, last_ch); if (brkt_right_ptr) { size_t brkt_index = brkt_right_ptr - brkts_right; char brkt_left = brkts_left[brkt_index]; const char *left = strrchr(name, brkt_left); if (left) { // Check for bus range. const char range_sep = ':'; const char *range = strchr(name, range_sep); if (range) { size_t bus_name_len = left - name; bus_name = new char[bus_name_len + 1]; strncpy(bus_name, name, bus_name_len); bus_name[bus_name_len] = '\0'; // No need to terminate bus subscript because atoi stops // scanning at first non-digit character. from = atoi(left + 1); to = atoi(range + 1); } } } } } const char * escapeChars(const char *token, char ch1, char ch2, char escape) { int result_length = 0; bool need_escapes = false; for (const char *s = token; *s; s++) { char ch = *s; if (ch == escape) { char next_ch = s[1]; // Make sure we don't skip the null if escape is the last char. if (next_ch != '\0') result_length++; } else if (ch == ch1 || ch == ch2) { result_length++; need_escapes = true; } result_length++; } if (need_escapes) { char *result = makeTmpString(result_length + 1); char *r = result; for (const char *s = token; *s; s++) { char ch = *s; if (ch == escape) { char next_ch = s[1]; // Make sure we don't skip the null if escape is the last char. if (next_ch != '\0') { *r++ = ch; *r++ = next_ch; s++; } } else if (ch == ch1 || ch == ch2) { *r++ = escape; *r++ = ch; } else *r++ = ch; } *r++ = '\0'; return result; } else return token; } } // namespace