diff options
author | golem galvanize <golemgalvanize@github.com> | 2018-01-09 16:48:01 -0500 |
---|---|---|
committer | golem galvanize <golemgalvanize@github.com> | 2018-01-09 16:48:01 -0500 |
commit | c7722a492017dbd8a5fb3bb216062eb62129daf5 (patch) | |
tree | 2a5c0ba6a6b9364aa93eb4a9a89b35153954ab63 /tools | |
parent | 2d141bc612ffecc984f6b4238c2791ba8419a192 (diff) | |
parent | 85174ad6193d3d58b92deaaedf8c510440ed85ee (diff) |
fixing merge conflicts
Diffstat (limited to 'tools')
-rw-r--r-- | tools/gbagfx/convert_png.c | 277 | ||||
-rw-r--r-- | tools/gbagfx/convert_png.h | 1 | ||||
-rw-r--r-- | tools/gbagfx/main.c | 9 | ||||
-rw-r--r-- | tools/preproc/c_file.cpp | 2 | ||||
-rw-r--r-- | tools/preproc/preproc.cpp | 4 | ||||
-rw-r--r-- | tools/scaninc/c_file.cpp | 175 | ||||
-rw-r--r-- | tools/scaninc/c_file.h | 6 | ||||
-rw-r--r-- | tools/scaninc/scaninc.cpp | 94 |
8 files changed, 374 insertions, 194 deletions
diff --git a/tools/gbagfx/convert_png.c b/tools/gbagfx/convert_png.c index f6a30804a..cdfa39a7a 100644 --- a/tools/gbagfx/convert_png.c +++ b/tools/gbagfx/convert_png.c @@ -7,163 +7,248 @@ #include "convert_png.h" #include "gfx.h" +static FILE *PngReadOpen(char *path, png_structp *pngStruct, png_infop *pngInfo) +{ + FILE *fp = fopen(path, "rb"); + + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + + unsigned char sig[8]; + + if (fread(sig, 8, 1, fp) != 1) + FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path); + + if (png_sig_cmp(sig, 0, 8)) + FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path); + + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + + if (!png_ptr) + FATAL_ERROR("Failed to create PNG read struct.\n"); + + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); + + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path); + + png_init_io(png_ptr, fp); + png_set_sig_bytes(png_ptr, 8); + png_read_info(png_ptr, info_ptr); + + *pngStruct = png_ptr; + *pngInfo = info_ptr; + + return fp; +} + +static unsigned char *ConvertBitDepth(unsigned char *src, int srcBitDepth, int destBitDepth, int numPixels) +{ + // Round the number of bits up to the next 8 and divide by 8 to get the number of bytes. + int srcSize = ((numPixels * srcBitDepth + 7) & ~7) / 8; + int destSize = ((numPixels * destBitDepth + 7) & ~7) / 8; + unsigned char *output = calloc(destSize, 1); + unsigned char *dest = output; + int i; + int j; + int destBit = 8 - destBitDepth; + + for (i = 0; i < srcSize; i++) + { + unsigned char srcByte = src[i]; + + for (j = 8 - srcBitDepth; j >= 0; j -= srcBitDepth) + { + unsigned char pixel = (srcByte >> j) % (1 << srcBitDepth); + + if (pixel >= (1 << destBitDepth)) + FATAL_ERROR("Image exceeds the maximum color value for a %ibpp image.\n", destBitDepth); + *dest |= pixel << destBit; + destBit -= destBitDepth; + if (destBit < 0) + { + dest++; + destBit = 8 - destBitDepth; + } + } + } + + return output; +} + void ReadPng(char *path, struct Image *image) { - FILE *fp = fopen(path, "rb"); + png_structp png_ptr; + png_infop info_ptr; - if (fp == NULL) - FATAL_ERROR("Failed to open \"%s\" for reading.\n", path); + FILE *fp = PngReadOpen(path, &png_ptr, &info_ptr); - unsigned char sig[8]; + int bit_depth = png_get_bit_depth(png_ptr, info_ptr); - if (fread(sig, 8, 1, fp) != 1) - FATAL_ERROR("Failed to read PNG signature from \"%s\".\n", path); + int color_type = png_get_color_type(png_ptr, info_ptr); - if (png_sig_cmp(sig, 0, 8)) - FATAL_ERROR("\"%s\" does not have a valid PNG signature.\n", path); + if (color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_PALETTE) + FATAL_ERROR("\"%s\" has an unsupported color type.\n", path); - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + // Check if the image has a palette so that we can tell if the colors need to be inverted later. + // Don't read the palette because it's not needed for now. + image->hasPalette = (color_type == PNG_COLOR_TYPE_PALETTE); - if (!png_ptr) - FATAL_ERROR("Failed to create PNG read struct.\n"); + image->width = png_get_image_width(png_ptr, info_ptr); + image->height = png_get_image_height(png_ptr, info_ptr); - png_infop info_ptr = png_create_info_struct(png_ptr); + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); - if (!info_ptr) - FATAL_ERROR("Failed to create PNG info struct.\n"); + image->pixels = malloc(image->height * rowbytes); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Failed to init I/O for reading \"%s\".\n", path); + if (image->pixels == NULL) + FATAL_ERROR("Failed to allocate pixel buffer.\n"); - png_init_io(png_ptr, fp); - png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); - int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); - if (bit_depth != image->bitDepth) - FATAL_ERROR("\"%s\" has a bit depth of %d, but the expected bit depth is %d.\n", path, bit_depth, image->bitDepth); + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); - int color_type = png_get_color_type(png_ptr, info_ptr); + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error reading from \"%s\".\n", path); - if (color_type != PNG_COLOR_TYPE_GRAY && color_type != PNG_COLOR_TYPE_PALETTE) - FATAL_ERROR("\"%s\" has an unsupported color type.\n", path); + png_read_image(png_ptr, row_pointers); - // Check if the image has a palette so that we can tell if the colors need to be inverted later. - // Don't read the palette because it's not needed for now. - image->hasPalette = (color_type == PNG_COLOR_TYPE_PALETTE); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - image->width = png_get_image_width(png_ptr, info_ptr); - image->height = png_get_image_height(png_ptr, info_ptr); + free(row_pointers); + fclose(fp); - int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + if (bit_depth != image->bitDepth) + { + unsigned char *src = image->pixels; - image->pixels = malloc(image->height * rowbytes); + if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && bit_depth != 8) + FATAL_ERROR("Bit depth of image must be 1, 2, 4, or 8.\n"); + image->pixels = ConvertBitDepth(image->pixels, bit_depth, image->bitDepth, image->width * image->height); + free(src); + image->bitDepth = bit_depth; + } +} - if (image->pixels == NULL) - FATAL_ERROR("Failed to allocate pixel buffer.\n"); +void ReadPngPalette(char *path, struct Palette *palette) +{ + png_structp png_ptr; + png_infop info_ptr; + png_colorp colors; + int numColors; - png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + FILE *fp = PngReadOpen(path, &png_ptr, &info_ptr); - if (row_pointers == NULL) - FATAL_ERROR("Failed to allocate row pointers.\n"); + if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_PALETTE) + FATAL_ERROR("The image \"%s\" does not contain a palette.\n", path); - for (int i = 0; i < image->height; i++) - row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + if (png_get_PLTE(png_ptr, info_ptr, &colors, &numColors) != PNG_INFO_PLTE) + FATAL_ERROR("Failed to retrieve palette from \"%s\".\n", path); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Error reading from \"%s\".\n", path); + if (numColors > 256) + FATAL_ERROR("Images with more than 256 colors are not supported.\n"); - png_read_image(png_ptr, row_pointers); + palette->numColors = numColors; + for (int i = 0; i < numColors; i++) { + palette->colors[i].red = colors[i].red; + palette->colors[i].green = colors[i].green; + palette->colors[i].blue = colors[i].blue; + } - png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); - free(row_pointers); - fclose(fp); + fclose(fp); } void SetPngPalette(png_structp png_ptr, png_infop info_ptr, struct Palette *palette) { - png_colorp colors = malloc(palette->numColors * sizeof(png_color)); + png_colorp colors = malloc(palette->numColors * sizeof(png_color)); - if (colors == NULL) - FATAL_ERROR("Failed to allocate PNG palette.\n"); + if (colors == NULL) + FATAL_ERROR("Failed to allocate PNG palette.\n"); - for (int i = 0; i < palette->numColors; i++) { - colors[i].red = palette->colors[i].red; - colors[i].green = palette->colors[i].green; - colors[i].blue = palette->colors[i].blue; - } + for (int i = 0; i < palette->numColors; i++) { + colors[i].red = palette->colors[i].red; + colors[i].green = palette->colors[i].green; + colors[i].blue = palette->colors[i].blue; + } - png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors); + png_set_PLTE(png_ptr, info_ptr, colors, palette->numColors); - free(colors); + free(colors); } void WritePng(char *path, struct Image *image) { - FILE *fp = fopen(path, "wb"); + FILE *fp = fopen(path, "wb"); - if (fp == NULL) - FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); + if (fp == NULL) + FATAL_ERROR("Failed to open \"%s\" for writing.\n", path); - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) - FATAL_ERROR("Failed to create PNG write struct.\n"); + if (!png_ptr) + FATAL_ERROR("Failed to create PNG write struct.\n"); - png_infop info_ptr = png_create_info_struct(png_ptr); + png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) - FATAL_ERROR("Failed to create PNG info struct.\n"); + if (!info_ptr) + FATAL_ERROR("Failed to create PNG info struct.\n"); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path); + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Failed to init I/O for writing \"%s\".\n", path); - png_init_io(png_ptr, fp); + png_init_io(png_ptr, fp); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Error writing header for \"%s\".\n", path); + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing header for \"%s\".\n", path); - int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY; + int color_type = image->hasPalette ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_GRAY; - png_set_IHDR(png_ptr, info_ptr, image->width, image->height, - image->bitDepth, color_type, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + image->bitDepth, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - if (image->hasPalette) { - SetPngPalette(png_ptr, info_ptr, &image->palette); + if (image->hasPalette) { + SetPngPalette(png_ptr, info_ptr, &image->palette); - if (image->hasTransparency) { - png_byte trans = 0; - png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0); - } - } + if (image->hasTransparency) { + png_byte trans = 0; + png_set_tRNS(png_ptr, info_ptr, &trans, 1, 0); + } + } - png_write_info(png_ptr, info_ptr); + png_write_info(png_ptr, info_ptr); - png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); + png_bytepp row_pointers = malloc(image->height * sizeof(png_bytep)); - if (row_pointers == NULL) - FATAL_ERROR("Failed to allocate row pointers.\n"); + if (row_pointers == NULL) + FATAL_ERROR("Failed to allocate row pointers.\n"); - int rowbytes = png_get_rowbytes(png_ptr, info_ptr); + int rowbytes = png_get_rowbytes(png_ptr, info_ptr); - for (int i = 0; i < image->height; i++) - row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); + for (int i = 0; i < image->height; i++) + row_pointers[i] = (png_bytep)(image->pixels + (i * rowbytes)); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Error writing \"%s\".\n", path); + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error writing \"%s\".\n", path); - png_write_image(png_ptr, row_pointers); + png_write_image(png_ptr, row_pointers); - if (setjmp(png_jmpbuf(png_ptr))) - FATAL_ERROR("Error ending write of \"%s\".\n", path); + if (setjmp(png_jmpbuf(png_ptr))) + FATAL_ERROR("Error ending write of \"%s\".\n", path); - png_write_end(png_ptr, NULL); + png_write_end(png_ptr, NULL); - fclose(fp); + fclose(fp); - png_destroy_write_struct(&png_ptr, &info_ptr); - free(row_pointers); + png_destroy_write_struct(&png_ptr, &info_ptr); + free(row_pointers); } diff --git a/tools/gbagfx/convert_png.h b/tools/gbagfx/convert_png.h index 55d3d6942..caf081b73 100644 --- a/tools/gbagfx/convert_png.h +++ b/tools/gbagfx/convert_png.h @@ -7,5 +7,6 @@ void ReadPng(char *path, struct Image *image); void WritePng(char *path, struct Image *image); +void ReadPngPalette(char *path, struct Palette *palette); #endif // CONVERT_PNG_H diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c index 37d3441fe..97db60e84 100644 --- a/tools/gbagfx/main.c +++ b/tools/gbagfx/main.c @@ -134,6 +134,14 @@ void HandlePngToGbaCommand(char *inputPath, char *outputPath, int argc, char **a ConvertPngToGba(inputPath, outputPath, numTiles, bitDepth); } +void HandlePngToGbaPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) +{ + struct Palette palette; + + ReadPngPalette(inputPath, &palette); + WriteGbaPalette(outputPath, &palette); +} + void HandleGbaToJascPaletteCommand(char *inputPath, char *outputPath, int argc UNUSED, char **argv UNUSED) { struct Palette palette; @@ -353,6 +361,7 @@ int main(int argc, char **argv) { "png", "1bpp", HandlePngToGbaCommand }, { "png", "4bpp", HandlePngToGbaCommand }, { "png", "8bpp", HandlePngToGbaCommand }, + { "png", "gbapal", HandlePngToGbaPaletteCommand }, { "gbapal", "pal", HandleGbaToJascPaletteCommand }, { "pal", "gbapal", HandleJascToGbaPaletteCommand }, { "latfont", "png", HandleLatinFontToPngCommand }, diff --git a/tools/preproc/c_file.cpp b/tools/preproc/c_file.cpp index 5bfdee086..24b3453e8 100644 --- a/tools/preproc/c_file.cpp +++ b/tools/preproc/c_file.cpp @@ -139,6 +139,7 @@ bool CFile::ConsumeNewline() { m_pos += 2; m_lineNum++; + std::putchar('\n'); return true; } @@ -146,6 +147,7 @@ bool CFile::ConsumeNewline() { m_pos++; m_lineNum++; + std::putchar('\n'); return true; } diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 8320a2d27..c9c6042df 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -89,8 +89,8 @@ void PreprocAsmFile(std::string filename) if (globalLabel.length() != 0) { - std::printf("\t.global %s\n", globalLabel.c_str()); - std::printf("%s:\n", globalLabel.c_str()); + const char *s = globalLabel.c_str(); + std::printf("%s: ; .global %s\n", s, s); } else { diff --git a/tools/scaninc/c_file.cpp b/tools/scaninc/c_file.cpp index b82276dd6..f7acc833f 100644 --- a/tools/scaninc/c_file.cpp +++ b/tools/scaninc/c_file.cpp @@ -45,8 +45,6 @@ CFile::CFile(std::string path) m_pos = 0; m_lineNum = 1; - - RemoveComments(); } CFile::~CFile() @@ -54,71 +52,6 @@ CFile::~CFile() delete[] m_buffer; } -// Removes comments to simplify further processing. -// It stops upon encountering a null character, -// which may or may not be the end of file marker. -// If it's not, the error will be caught later. -void CFile::RemoveComments() -{ - long pos = 0; - char stringChar = 0; - - for (;;) - { - if (m_buffer[pos] == 0) - return; - - if (stringChar != 0) - { - if (m_buffer[pos] == '\\' && m_buffer[pos + 1] == stringChar) - { - pos += 2; - } - else - { - if (m_buffer[pos] == stringChar) - stringChar = 0; - pos++; - } - } - else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '/') - { - while (m_buffer[pos] != '\n' && m_buffer[pos] != 0) - m_buffer[pos++] = ' '; - } - else if (m_buffer[pos] == '/' && m_buffer[pos + 1] == '*') - { - m_buffer[pos++] = ' '; - m_buffer[pos++] = ' '; - - for (;;) - { - if (m_buffer[pos] == 0) - return; - - if (m_buffer[pos] == '*' && m_buffer[pos + 1] == '/') - { - m_buffer[pos++] = ' '; - m_buffer[pos++] = ' '; - break; - } - else - { - if (m_buffer[pos] != '\n') - m_buffer[pos] = ' '; - pos++; - } - } - } - else - { - if (m_buffer[pos] == '"' || m_buffer[pos] == '\'') - stringChar = m_buffer[pos]; - pos++; - } - } -} - void CFile::FindIncbins() { char stringChar = 0; @@ -145,6 +78,8 @@ void CFile::FindIncbins() } else { + SkipWhitespace(); + CheckInclude(); CheckIncbin(); if (m_pos >= m_size) @@ -177,6 +112,13 @@ bool CFile::ConsumeHorizontalWhitespace() bool CFile::ConsumeNewline() { + if (m_buffer[m_pos] == '\n') + { + m_pos++; + m_lineNum++; + return true; + } + if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') { m_pos += 2; @@ -184,10 +126,33 @@ bool CFile::ConsumeNewline() return true; } - if (m_buffer[m_pos] == '\n') + return false; +} + +bool CFile::ConsumeComment() +{ + if (m_buffer[m_pos] == '/' && m_buffer[m_pos + 1] == '*') { - m_pos++; - m_lineNum++; + m_pos += 2; + while (m_buffer[m_pos] != '*' && m_buffer[m_pos + 1] != '/') + { + if (m_buffer[m_pos] == 0) + return false; + if (!ConsumeNewline()) + m_pos++; + } + m_pos += 2; + return true; + } + else if (m_buffer[m_pos] == '/' && m_buffer[m_pos + 1] == '/') + { + m_pos += 2; + while (!ConsumeNewline()) + { + if (m_buffer[m_pos] == 0) + return false; + m_pos++; + } return true; } @@ -196,7 +161,7 @@ bool CFile::ConsumeNewline() void CFile::SkipWhitespace() { - while (ConsumeHorizontalWhitespace() || ConsumeNewline()) + while (ConsumeHorizontalWhitespace() || ConsumeNewline() || ConsumeComment()) ; } @@ -211,8 +176,43 @@ bool CFile::CheckIdentifier(const std::string& ident) return (i == ident.length()); } +void CFile::CheckInclude() +{ + if (m_buffer[m_pos] != '#') + return; + + std::string ident = "#include"; + + if (!CheckIdentifier(ident)) + { + return; + } + + m_pos += ident.length(); + + ConsumeHorizontalWhitespace(); + + std::string path = ReadPath(); + + if (!path.empty()) { + m_includes.emplace(path); + } +} + void CFile::CheckIncbin() { + // Optimization: assume most lines are not incbins + if (!(m_buffer[m_pos+0] == 'I' + && m_buffer[m_pos+1] == 'N' + && m_buffer[m_pos+2] == 'C' + && m_buffer[m_pos+3] == 'B' + && m_buffer[m_pos+4] == 'I' + && m_buffer[m_pos+5] == 'N' + && m_buffer[m_pos+6] == '_')) + { + return; + } + std::string idents[6] = { "INCBIN_S8", "INCBIN_U8", "INCBIN_S16", "INCBIN_U16", "INCBIN_S32", "INCBIN_U32" }; int incbinType = -1; @@ -246,8 +246,28 @@ void CFile::CheckIncbin() SkipWhitespace(); + std::string path = ReadPath(); + + SkipWhitespace(); + + if (m_buffer[m_pos] != ')') + FATAL_INPUT_ERROR("expected ')'"); + + m_pos++; + + m_incbins.emplace(path); +} + +std::string CFile::ReadPath() +{ if (m_buffer[m_pos] != '"') - FATAL_INPUT_ERROR("expected double quote"); + { + if (m_buffer[m_pos] == '<') + { + return std::string(); + } + FATAL_INPUT_ERROR("expected '\"' or '<'"); + } m_pos++; @@ -272,16 +292,7 @@ void CFile::CheckIncbin() m_pos++; } - std::string path(&m_buffer[startPos], m_pos - startPos); - m_pos++; - SkipWhitespace(); - - if (m_buffer[m_pos] != ')') - FATAL_INPUT_ERROR("expected ')'"); - - m_pos++; - - m_incbins.emplace(path); + return std::string(m_buffer + startPos, m_pos - 1 - startPos); } diff --git a/tools/scaninc/c_file.h b/tools/scaninc/c_file.h index 922cb4639..618901b85 100644 --- a/tools/scaninc/c_file.h +++ b/tools/scaninc/c_file.h @@ -33,6 +33,7 @@ public: ~CFile(); void FindIncbins(); const std::set<std::string>& GetIncbins() { return m_incbins; } + const std::set<std::string>& GetIncludes() { return m_includes; } private: char *m_buffer; @@ -41,13 +42,16 @@ private: int m_lineNum; std::string m_path; std::set<std::string> m_incbins; + std::set<std::string> m_includes; - void RemoveComments(); bool ConsumeHorizontalWhitespace(); bool ConsumeNewline(); + bool ConsumeComment(); void SkipWhitespace(); bool CheckIdentifier(const std::string& ident); + void CheckInclude(); void CheckIncbin(); + std::string ReadPath(); }; #endif // C_FILE_H diff --git a/tools/scaninc/scaninc.cpp b/tools/scaninc/scaninc.cpp index b6f7ba767..3dc221479 100644 --- a/tools/scaninc/scaninc.cpp +++ b/tools/scaninc/scaninc.cpp @@ -20,7 +20,8 @@ #include <cstdio> #include <cstdlib> -#include <stack> +#include <list> +#include <queue> #include <set> #include <string> #include "scaninc.h" @@ -38,15 +39,49 @@ bool CanOpenFile(std::string path) return true; } +const char *const USAGE = "Usage: scaninc [-I INCLUDE_PATH] FILE_PATH\n"; + int main(int argc, char **argv) { - if (argc < 2) - FATAL_ERROR("Usage: scaninc FILE_PATH\n"); - - std::stack<std::string> filesToProcess; + std::queue<std::string> filesToProcess; std::set<std::string> dependencies; - std::string initialPath(argv[1]); + std::list<std::string> includeDirs; + + argc--; + argv++; + + while (argc > 1) + { + std::string arg(argv[0]); + if (arg.substr(0, 2) == "-I") + { + std::string includeDir = arg.substr(2); + if (includeDir.empty()) + { + argc--; + argv++; + includeDir = std::string(argv[0]); + } + if (includeDir.back() != '/') + { + includeDir += '/'; + } + includeDirs.push_back(includeDir); + } + else + { + FATAL_ERROR(USAGE); + } + argc--; + argv++; + } + + if (argc != 1) { + FATAL_ERROR(USAGE); + } + + std::string initialPath(argv[0]); std::size_t pos = initialPath.find_last_of('.'); @@ -55,20 +90,53 @@ int main(int argc, char **argv) std::string extension = initialPath.substr(pos + 1); - if (extension == "c") + std::string srcDir(""); + std::size_t slash = initialPath.rfind('/'); + if (slash != std::string::npos) { - CFile file(initialPath); + srcDir = initialPath.substr(0, slash + 1); + } + includeDirs.push_back(srcDir); + + if (extension == "c" || extension == "h") + { + filesToProcess.push(initialPath); + + while (!filesToProcess.empty()) + { + CFile file(filesToProcess.front()); + filesToProcess.pop(); - file.FindIncbins(); - dependencies = file.GetIncbins(); + file.FindIncbins(); + for (auto incbin : file.GetIncbins()) + { + dependencies.insert(incbin); + } + for (auto include : file.GetIncludes()) + { + for (auto includeDir : includeDirs) + { + std::string path(includeDir + include); + if (CanOpenFile(path)) + { + bool inserted = dependencies.insert(path).second; + if (inserted) + { + filesToProcess.push(path); + } + break; + } + } + } + } } - else if (extension == "s") + else if (extension == "s" || extension == "inc") { - filesToProcess.push(std::string(argv[1])); + filesToProcess.push(initialPath); while (!filesToProcess.empty()) { - AsmFile file(filesToProcess.top()); + AsmFile file(filesToProcess.front()); filesToProcess.pop(); |