diff options
author | YamaArashi <shadow962@live.com> | 2017-01-23 16:34:20 -0800 |
---|---|---|
committer | YamaArashi <shadow962@live.com> | 2017-01-23 21:31:28 -0800 |
commit | c8542506580c0fa247bbb44c169a2cb1244577e4 (patch) | |
tree | 904e4c48d51b0452f8b1c8194a8ac636e7ea1657 /tools/scaninc/scaninc.cpp | |
parent | 535ed69d33072543b543829b86409758cc7f6318 (diff) |
preproc incbins
Diffstat (limited to 'tools/scaninc/scaninc.cpp')
-rw-r--r-- | tools/scaninc/scaninc.cpp | 382 |
1 files changed, 81 insertions, 301 deletions
diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp index 3bd6b81a5..2f9ed81e9 100644 --- a/tools/scaninc/scaninc.cpp +++ b/tools/scaninc/scaninc.cpp @@ -1,317 +1,97 @@ -// Copyright (c) 2015 YamaArashi +// Copyright(c) 2015-2017 YamaArashi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. #include <cstdio> #include <cstdlib> #include <stack> #include <set> #include <string> - -#ifdef _MSC_VER - -#define FATAL_INPUT_ERROR(format, ...) \ -do { \ - fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, __VA_ARGS__); \ - exit(1); \ -} while (0) - -#define FATAL_ERROR(format, ...) \ -do { \ - fprintf(stderr, format, __VA_ARGS__); \ - exit(1); \ -} while (0) - -#else - -#define FATAL_INPUT_ERROR(format, ...) \ -do { \ - fprintf(stderr, "%s:%d " format, m_path.c_str(), m_lineNum, ##__VA_ARGS__); \ - exit(1); \ -} while (0) - -#define FATAL_ERROR(format, ...) \ -do { \ - fprintf(stderr, format, ##__VA_ARGS__); \ - exit(1); \ -} while (0) - -#endif // _MSC_VER - -#define SCANINC_MAX_PATH 255 - -enum class IncDirectiveType { - None, - Include, - Incbin -}; - -class AsmFile -{ -public: - AsmFile(std::string path); - ~AsmFile(); - IncDirectiveType ReadUntilIncDirective(std::string &path); - -private: - char *m_buffer; - int m_pos; - int m_size; - int m_lineNum; - std::string m_path; - - int GetChar() - { - if (m_pos >= m_size) - return -1; - - int c = m_buffer[m_pos++]; - - if (c == '\r') { - if (m_pos < m_size && m_buffer[m_pos++] == '\n') { - m_lineNum++; - return '\n'; - } else { - FATAL_INPUT_ERROR("CR line endings are not supported\n"); - } - } - - if (c == '\n') - m_lineNum++; - - return c; - } - - // No newline translation because it's not needed for any use of this function. - int PeekChar() - { - if (m_pos >= m_size) - return -1; - - return m_buffer[m_pos]; - } - - void SkipTabsAndSpaces() - { - while (m_pos < m_size && (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ')) - m_pos++; - } - - bool MatchIncDirective(std::string directiveName, std::string &path) - { - int length = directiveName.length(); - int i; - - for (i = 0; i < length && m_pos + i < m_size; i++) - if (directiveName[i] != m_buffer[m_pos + i]) - return false; - - if (i < length) - return false; - - m_pos += length; - - SkipTabsAndSpaces(); - - if (GetChar() != '"') - FATAL_INPUT_ERROR("no path after \".%s\" directive\n", directiveName.c_str()); - - path = ReadPath(); - - return true; - } - - std::string ReadPath(); - void SkipEndOfLineComment(); - void SkipMultiLineComment(); - void SkipString(); -}; - -AsmFile::AsmFile(std::string path) -{ - m_path = path; - - FILE *fp = fopen(path.c_str(), "rb"); - - if (fp == NULL) - FATAL_ERROR("Failed to open \"%s\" for reading.\n", path.c_str()); - - fseek(fp, 0, SEEK_END); - - m_size = ftell(fp); - - m_buffer = new char[m_size]; - - rewind(fp); - - if (fread(m_buffer, m_size, 1, fp) != 1) - FATAL_ERROR("Failed to read \"%s\".\n", path.c_str()); - - fclose(fp); - - m_pos = 0; - m_lineNum = 1; -} - -AsmFile::~AsmFile() -{ - delete[] m_buffer; -} - -IncDirectiveType AsmFile::ReadUntilIncDirective(std::string &path) -{ - // At the beginning of each loop iteration, the current file position - // should be at the start of a line or at the end of the file. - for (;;) { - SkipTabsAndSpaces(); - - IncDirectiveType incDirectiveType = IncDirectiveType::None; - - if (PeekChar() == '.') { - m_pos++; - - if (MatchIncDirective("incbin", path)) - incDirectiveType = IncDirectiveType::Incbin; - else if (MatchIncDirective("include", path)) - incDirectiveType = IncDirectiveType::Include; - } - - for (;;) { - int c = GetChar(); - - if (c == -1) - return incDirectiveType; - - if (c == ';') { - SkipEndOfLineComment(); - break; - } else if (c == '/' && PeekChar() == '*') { - m_pos++; - SkipMultiLineComment(); - } else if (c == '"') { - SkipString(); - } else if (c == '\n') { - break; - } - } - - if (incDirectiveType != IncDirectiveType::None) - return incDirectiveType; - } -} - -std::string AsmFile::ReadPath() -{ - int length = 0; - int startPos = m_pos; - - for (;;) { - int c = GetChar(); - - if (c == '"') - break; - - if (c == -1) - FATAL_INPUT_ERROR("unexpected EOF in include string\n"); - - if (c == 0) - FATAL_INPUT_ERROR("unexpected NUL character in include string\n"); - - if (c == '\n') - FATAL_INPUT_ERROR("unexpected end of line character in include string\n"); - - // Don't bother allowing any escape sequences. - if (c == '\\') - FATAL_INPUT_ERROR("unexpected escape '\\%c' in include string\n", c); - - length++; - - if (length > SCANINC_MAX_PATH) - FATAL_INPUT_ERROR("path is too long"); - } - - return std::string(m_buffer, startPos, length); -} - -void AsmFile::SkipEndOfLineComment() -{ - int c; - - do { - c = GetChar(); - } while (c != -1 && c != '\n'); -} - -void AsmFile::SkipMultiLineComment() -{ - for (;;) { - int c = GetChar(); - - if (c == '*') { - if (PeekChar() == '/') { - m_pos++; - return; - } - } else if (c == -1) { - return; - } - } -} - -void AsmFile::SkipString() -{ - for (;;) { - int c = GetChar(); - - if (c == '"') - break; - - if (c == -1) - FATAL_INPUT_ERROR("unexpected EOF in string\n"); - - if (c == '\\') { - c = GetChar(); - } - } -} +#include "scaninc.h" +#include "asm_file.h" +#include "c_file.h" bool CanOpenFile(std::string path) { - FILE *fp = fopen(path.c_str(), "rb"); + FILE *fp = fopen(path.c_str(), "rb"); - if (fp == NULL) - return false; + if (fp == NULL) + return false; - fclose(fp); - return true; + fclose(fp); + return true; } int main(int argc, char **argv) { - if (argc < 2) - FATAL_ERROR("Usage: scaninc ASM_FILE_PATH\n"); - - std::stack<std::string> filesToProcess; - std::set<std::string> dependencies; - - filesToProcess.push(std::string(argv[1])); - - while (!filesToProcess.empty()) { - AsmFile file(filesToProcess.top()); - - filesToProcess.pop(); - - IncDirectiveType incDirectiveType; - std::string path; - - while ((incDirectiveType = file.ReadUntilIncDirective(path)) != IncDirectiveType::None) { - bool inserted = dependencies.insert(path).second; - if (inserted - && incDirectiveType == IncDirectiveType::Include - && CanOpenFile(path)) - filesToProcess.push(path); - } - } - - for (const std::string &path : dependencies) { - printf("%s\n", path.c_str()); - } + if (argc < 2) + FATAL_ERROR("Usage: scaninc FILE_PATH\n"); + + std::stack<std::string> filesToProcess; + std::set<std::string> dependencies; + + std::string initialPath(argv[1]); + + std::size_t pos = initialPath.find_last_of('.'); + + if (pos == std::string::npos) + FATAL_ERROR("no file extension in path \"%s\"\n", initialPath.c_str()); + + std::string extension = initialPath.substr(pos + 1); + + if (extension == "c") + { + CFile file(initialPath); + + file.FindIncbins(); + dependencies = file.GetIncbins(); + } + else if (extension == "s") + { + filesToProcess.push(std::string(argv[1])); + + while (!filesToProcess.empty()) + { + AsmFile file(filesToProcess.top()); + + filesToProcess.pop(); + + IncDirectiveType incDirectiveType; + std::string path; + + while ((incDirectiveType = file.ReadUntilIncDirective(path)) != IncDirectiveType::None) + { + bool inserted = dependencies.insert(path).second; + if (inserted + && incDirectiveType == IncDirectiveType::Include + && CanOpenFile(path)) + filesToProcess.push(path); + } + } + } + else + { + FATAL_ERROR("unknown extension \"%s\"\n", extension.c_str()); + } + + for (const std::string &path : dependencies) + { + printf("%s\n", path.c_str()); + } } |