summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--prelude/CMakeLists.txt4
-rw-r--r--tools/slang-embed/slang-embed.cpp160
2 files changed, 135 insertions, 29 deletions
diff --git a/prelude/CMakeLists.txt b/prelude/CMakeLists.txt
index 27acd49f9..913809f07 100644
--- a/prelude/CMakeLists.txt
+++ b/prelude/CMakeLists.txt
@@ -12,8 +12,8 @@ foreach(input ${prelude_headers})
add_custom_command(
OUTPUT ${output}
COMMAND
- slang-embed "${input}" "${CMAKE_CURRENT_LIST_DIR}/../include"
- ${output}
+ slang-embed "${input}" ${output}
+ "-I$<JOIN:$<TARGET_PROPERTY:core,INCLUDE_DIRECTORIES>, -I>"
DEPENDS ${input} slang-embed
VERBATIM
)
diff --git a/tools/slang-embed/slang-embed.cpp b/tools/slang-embed/slang-embed.cpp
index 8cba887f3..622ecea65 100644
--- a/tools/slang-embed/slang-embed.cpp
+++ b/tools/slang-embed/slang-embed.cpp
@@ -63,47 +63,110 @@ struct App
{
char const* appName = "slang-embed";
char const* inputPath = nullptr;
- char const* includeDir = nullptr;
char const* outputPath = nullptr;
+ Slang::List<Slang::String> includeDirs;
Slang::HashSet<Slang::String> includedFiles;
+ size_t charCount = 0;
+ bool useNewStringLit = true;
void parseOptions(int argc, char** argv)
{
- // Options are currently all specified by position,
- // so the parsing logic is simplistic.
-
+ // First, get the program name
if (argc > 0)
{
appName = *argv++;
argc--;
}
- if (argc > 0)
+ // Parse remaining arguments - we need at least inputPath
+ if (argc < 1)
{
- inputPath = *argv++;
- argc--;
+ fprintf(stderr, "usage: %s inputPath [outputPath] [-I<includeDir> ...]\n", appName);
+ exit(1);
}
- if (argc > 0)
- {
- includeDir = *argv++;
- argc--;
- }
+ // Get input path (first positional argument)
+ inputPath = *argv++;
+ argc--;
- if (argc > 0)
+ // Process remaining arguments
+ while (argc > 0)
{
- outputPath = *argv++;
+ char* arg = *argv++;
argc--;
+
+ // Check for -I prefix for include directories
+ if (strncmp(arg, "-I", 2) == 0)
+ {
+ // Check if this is a concatenated string of include directories
+ char* startPtr = arg;
+
+ // Process the entire string as potentially multiple -I directives
+ while (startPtr && *startPtr)
+ {
+ // Find the -I prefix
+ char* iPos = strstr(startPtr, "-I");
+ if (!iPos)
+ break;
+
+ // Move past the -I
+ char* dirStart = iPos + 2;
+
+ // Find the next -I or end of string
+ char* nextIPos = strstr(dirStart, "-I");
+
+ // Determine end of current include dir
+ char* dirEnd = nextIPos ? nextIPos : (startPtr + strlen(startPtr));
+
+ // Check if the directory has a semicolon or quotes at the end
+ if (dirEnd > dirStart && (*(dirEnd - 1) == ';' || *(dirEnd - 1) == '"'))
+ dirEnd--;
+
+ // Save the current directory by creating a substring
+ if (dirEnd > dirStart)
+ {
+ // Create a null-terminated copy
+ size_t dirLen = dirEnd - dirStart;
+ Slang::String tempDir(Slang::UnownedStringSlice(dirStart, dirLen));
+
+ // Remove any quotes
+ if (tempDir[0] == '"')
+ tempDir = tempDir.subString(1, tempDir.getLength() - 1);
+ if (tempDir.endsWith("\"") && tempDir.getLength() > 0)
+ tempDir = tempDir.subString(0, tempDir.getLength() - 1);
+
+ // Remove trailing whitespace
+ tempDir = tempDir.trimEnd();
+
+ // Add to include dirs
+ includeDirs.add(tempDir);
+ }
+
+ // Move to next position (if any)
+ startPtr = nextIPos;
+ }
+ }
+ // Otherwise treat as output path if not already set
+ else if (!outputPath)
+ {
+ outputPath = arg;
+ }
+ else
+ {
+ fprintf(stderr, "unexpected argument: %s\n", arg);
+ fprintf(stderr, "usage: %s inputPath [outputPath] [-I<includeDir> ...]\n", appName);
+ exit(1);
+ }
}
- if (!inputPath || (argc != 0))
+ // Validate we have the required arguments
+ if (!inputPath)
{
- fprintf(stderr, "usage: %s inputPath includeDir [outputPath]\n", appName);
+ fprintf(stderr, "usage: %s inputPath [outputPath] [-I<includeDir> ...]\n", appName);
exit(1);
}
}
- size_t charCount = 0;
- bool useNewStringLit = true;
+
void processInputFile(FILE* outputFile, Slang::String inputPath)
{
using namespace Slang;
@@ -138,19 +201,62 @@ struct App
if (trimedLine.startsWith("#include"))
{
auto fileName = Slang::StringUtil::getAtInSplit(trimedLine, ' ', 1);
+ bool isSystemInclude = false;
+
+ // Handle both quoted and angle-bracket includes
if (fileName[0] == '<')
- goto normalProcess;
- fileName = Slang::UnownedStringSlice(fileName.begin() + 1, fileName.end() - 1);
- auto path =
- Slang::Path::combine(Slang::Path::getParentDirectory(inputPath), fileName);
- if (!Slang::File::exists(path))
{
- // Try looking in the include directory.
- path = Slang::Path::combine(includeDir, fileName);
+ // Handle <filename> format
+ isSystemInclude = true;
+ // Extract filename between < and >
+ if (fileName.getLength() >= 2 && fileName[fileName.getLength() - 1] == '>')
+ {
+ fileName =
+ Slang::UnownedStringSlice(fileName.begin() + 1, fileName.end() - 1);
+ }
+ else
+ {
+ goto normalProcess; // Malformed include, skip it
+ }
+ }
+ else if (fileName[0] == '"' && fileName[fileName.getLength() - 1] == '"')
+ {
+ // Handle "filename" format
+ fileName = Slang::UnownedStringSlice(fileName.begin() + 1, fileName.end() - 1);
+ }
+ else
+ {
+ // Malformed include, skip it
+ goto normalProcess;
+ }
+
+ // For system includes, only look in include dirs, not relative to current file
+ auto path = isSystemInclude ? Slang::String()
+ : Slang::Path::combine(
+ Slang::Path::getParentDirectory(inputPath),
+ fileName);
- if (!Slang::File::exists(path))
- goto normalProcess;
+ bool foundInclude = false;
+ if (isSystemInclude || !Slang::File::exists(path))
+ {
+ // Try looking in each of the include directories
+ for (auto& includeDir : includeDirs)
+ {
+ path = Slang::Path::combine(includeDir, fileName);
+ if (Slang::File::exists(path))
+ {
+ foundInclude = true;
+ break;
+ }
+ }
}
+ else
+ {
+ foundInclude = true;
+ }
+
+ if (!foundInclude)
+ goto normalProcess;
processInputFile(outputFile, path.getUnownedSlice());
continue;
}