Skip to content

Commit

Permalink
Add a command line option for specifying translate_on/translate_off c…
Browse files Browse the repository at this point in the history
…omment directives
  • Loading branch information
MikePopoloski committed Dec 31, 2024
1 parent f4a4af6 commit f03ccdb
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 2 deletions.
29 changes: 29 additions & 0 deletions docs/command-line-ref.dox
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,35 @@ By default library files are independent and will not inherit macros from the ma

Enables use of legacy source protection directives for compatibility with older tools.

`--translate-off-format <common>,<start>,<end>`

Specify the format of a "translate off" directive in a comment that denotes a span
of text that is skipped from processing (as if it had been commented out). All source
text between the start comment and the end comment will be skipped.

@note It is generally preferred to use `ifdef` directives instead for this functionality,
but legacy code may contain these directives in comment form so this option can be
used for compatibility.

The format of the argument is three comma-separated words containing alphanumeric
and underscore characters. The first word is the common keyword at the beginning
of the comment. The second word is the directive that starts a skipped region,
and the third is the directive that ends the region.

More than one of these options can be provided to skip regions with differing styles
in the same run of the tool.

For example, using an option like `--translate-off-format pragma,translate_off,translate_on`
will work with code like the following:

@code{.sv}
module m;
// pragma translate_off
... some code to skip ...
// pragma translate_on
endmodule
@endcode

`--obfuscate-ids`

Causes all identifiers in the preprocessed output to be replaced with obfuscated
Expand Down
5 changes: 5 additions & 0 deletions include/slang/driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ class SLANG_EXPORT Driver {
/// A set of preprocessor directives to be ignored.
std::vector<std::string> ignoreDirectives;

/// A set of options controlling translate-off comment directives.
std::vector<std::string> translateOffOptions;

/// @}
/// @name Parsing
/// @{
Expand Down Expand Up @@ -340,6 +343,8 @@ class SLANG_EXPORT Driver {

bool anyFailedLoads = false;
flat_hash_set<std::filesystem::path> activeCommandFiles;
std::vector<std::tuple<std::string_view, std::string_view, std::string_view>>
translateOffFormats;
std::unique_ptr<JsonWriter> jsonWriter;
};

Expand Down
3 changes: 3 additions & 0 deletions include/slang/util/String.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ void strToUpper(std::string& str);
/// The string is converted in place.
void strToLower(std::string& str);

/// Splits the provided string into substrings based on the provided delimiter.
std::vector<std::string_view> splitString(std::string_view str, char delimiter);

/// Converts a character to uppercase (assuming ASCII).
inline char charToUpper(char c) {
return (char)::toupper(c);
Expand Down
2 changes: 1 addition & 1 deletion scripts/diagnostics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ error BadOctalDigit "expected octal digit"
error BadDecimalDigit "expected decimal digit"
error BadHexDigit "expected hexadecimal digit"
error TooManyLexerErrors "lexer has encountered too many errors (input is a binary file?)"
error UnclosedTranslateOff "translate_off pragma missing a closing counterpart"
error UnclosedTranslateOff "missing '{}' counterpart for this directive"
warning unknown-escape-code UnknownEscapeCode "unknown character escape sequence '\\\\{}'"
warning nonstandard-escape-code NonstandardEscapeCode "non-standard character escape sequence '\\\\{}'"
warning invalid-source-encoding InvalidUTF8Seq "invalid UTF-8 sequence in source text"
Expand Down
39 changes: 39 additions & 0 deletions source/driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ void Driver::addStandardArgs() {
cmdLine.add("--enable-legacy-protect", options.enableLegacyProtect,
"If true, the preprocessor will support legacy protected envelope directives, "
"for compatibility with old Verilog tools");
cmdLine.add("--translate-off-format", options.translateOffOptions,
"Set a format for comment directives that mark a region of disabled "
"source text. The format is a common keyword, a start word, and an "
"end word, each separated by commas. For example, "
"'pragma,translate_off,translate_on'",
"<common>,<start>,<end>");

// Legacy vendor commands support
cmdLine.add(
Expand Down Expand Up @@ -504,6 +510,36 @@ bool Driver::processOptions() {
opt = true;
}

if (!options.translateOffOptions.empty()) {
bool anyBad = false;
for (auto& fmtStr : options.translateOffOptions) {
bool bad = false;
auto parts = splitString(fmtStr, ',');
if (parts.size() != 3)
bad = true;

for (auto part : parts) {
if (part.empty())
bad = true;

for (char c : part) {
if (!isAlphaNumeric(c) && c != '_')
bad = true;
}
}

if (bad)
printError(fmt::format("invalid format for translate-off-format: '{}'", fmtStr));
else
translateOffFormats.emplace_back(parts[0], parts[1], parts[2]);

anyBad |= bad;
}

if (anyBad)
return false;
}

if (!reportLoadErrors())
return false;

Expand Down Expand Up @@ -738,6 +774,9 @@ void Driver::addParseOptions(Bag& bag) const {
if (loptions.enableLegacyProtect)
loptions.commentHandlers["pragma"]["protect"] = {CommentHandler::Protect};

for (auto& [common, start, end] : translateOffFormats)
loptions.commentHandlers[common][start] = {CommentHandler::TranslateOff, end};

ParserOptions poptions;
poptions.languageVersion = languageVersion;
if (options.maxParseDepth.has_value())
Expand Down
4 changes: 3 additions & 1 deletion source/parsing/Lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,7 +1535,9 @@ void Lexer::scanDisabledRegion(std::string_view firstWord, std::string_view seco
while (true) {
char c = peek();
if (c == '\0' && reallyAtEnd()) {
addDiag(unclosedDiag, currentOffset() - lexemeLength());
auto& diag = addDiag(unclosedDiag, currentOffset() - lexemeLength());
if (unclosedDiag == diag::UnclosedTranslateOff)
diag << secondWord;
return;
}

Expand Down
16 changes: 16 additions & 0 deletions source/util/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,22 @@ void strToLower(std::string& str) {
std::ranges::transform(str, str.begin(), [](char c) { return charToLower(c); });
}

std::vector<std::string_view> splitString(std::string_view str, char delimiter) {
std::vector<std::string_view> result;
std::string_view::size_type index = 0;
while (true) {
auto nextIndex = str.find(delimiter, index);
if (nextIndex == std::string_view::npos) {
result.push_back(str.substr(index));
break;
}

result.push_back(str.substr(index, nextIndex - index));
index = nextIndex + 1;
}
return result;
}

int editDistance(std::string_view left, std::string_view right, bool allowReplacements,
int maxDistance) {
// See: http://en.wikipedia.org/wiki/Levenshtein_distance
Expand Down
13 changes: 13 additions & 0 deletions tests/unittests/DriverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,19 @@ TEST_CASE("Driver invalid timescale") {
CHECK(stderrContains("invalid value for time scale option"));
}

TEST_CASE("Driver invalid translate-off-format") {
auto guard = OS::captureOutput();

Driver driver;
driver.addStandardArgs();

const char* argv[] = {"testfoo", "--translate-off-format=a,b,c,d",
"--translate-off-format=a,,c", "--translate-off-format=a,^^,c"};
CHECK(driver.parseCommandLine(4, argv));
CHECK(!driver.processOptions());
CHECK(stderrContains("invalid format for translate-off-format"));
}

TEST_CASE("Driver invalid include dirs") {
auto guard = OS::captureOutput();

Expand Down

0 comments on commit f03ccdb

Please sign in to comment.