https://git.reactos.org/?p=reactos.git;a=commitdiff;h=79b2d9c2ff53237f797653...
commit 79b2d9c2ff53237f7976533d788a710a1738a40a Author: Jérôme Gardou jerome.gardou@reactos.org AuthorDate: Tue May 18 17:10:41 2021 +0200 Commit: Jérôme Gardou zefklop@users.noreply.github.com CommitDate: Wed May 19 22:50:29 2021 +0200
[TXT2NLS] Rewrite the tool
With support for multibyte codepages & glyph tables CORE-17571 --- sdk/tools/txt2nls/CMakeLists.txt | 5 +- sdk/tools/txt2nls/main.c | 19 -- sdk/tools/txt2nls/main.cpp | 547 +++++++++++++++++++++++++++++++++++++++ sdk/tools/txt2nls/nls.c | 246 ------------------ sdk/tools/txt2nls/precomp.h | 51 ---- sdk/tools/txt2nls/txt.c | 497 ----------------------------------- 6 files changed, 548 insertions(+), 817 deletions(-)
diff --git a/sdk/tools/txt2nls/CMakeLists.txt b/sdk/tools/txt2nls/CMakeLists.txt index 929e59539d9..8669da89d75 100644 --- a/sdk/tools/txt2nls/CMakeLists.txt +++ b/sdk/tools/txt2nls/CMakeLists.txt @@ -1,7 +1,4 @@
-list(APPEND SOURCE - main.c - txt.c - nls.c) +list(APPEND SOURCE main.cpp)
add_host_tool(txt2nls ${SOURCE}) diff --git a/sdk/tools/txt2nls/main.c b/sdk/tools/txt2nls/main.c deleted file mode 100644 index d45b3785ac4..00000000000 --- a/sdk/tools/txt2nls/main.c +++ /dev/null @@ -1,19 +0,0 @@ -/* - * PROJECT: ReactOS TXT to NLS Converter - * LICENSE: GNU General Public License Version 2.0 or any later version - * FILE: devutils/txt2nls/main.c - * COPYRIGHT: Copyright 2016 Dmitry Chapyshev dmitry@reactos.org - */ - -#include "precomp.h" - -int main(int argc, char* argv[]) -{ - if (argc != 3) - return 1; - - if (!nls_from_txt(argv[1], argv[2])) - return 1; - - return 0; -} diff --git a/sdk/tools/txt2nls/main.cpp b/sdk/tools/txt2nls/main.cpp new file mode 100644 index 00000000000..cb8ebb7572f --- /dev/null +++ b/sdk/tools/txt2nls/main.cpp @@ -0,0 +1,547 @@ +/* + * PROJECT: ReactOS TXT to NLS Converter + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later.html) + * FILE: sdk/tools/txt2nls/main.c + * COPYRIGHT: Copyright 2021 Jérôme Gardou jerome.gardou@reactos.org + */ + +#include <iostream> +#include <fstream> +#include <limits> +#include <vector> +#include <cstring> +#include <string> + +static const char whitespaces[] = " \t\f\v\n\r"; +static long line_number = -1; + +#pragma pack(push, 1) +#define MAXIMUM_LEADBYTES 12 +struct NLS_FILE_HEADER +{ + uint16_t HeaderSize; + uint16_t CodePage; + uint16_t MaximumCharacterSize; + uint16_t DefaultChar; + uint16_t UniDefaultChar; + uint16_t TransDefaultChar; + uint16_t TransUniDefaultChar; + uint8_t LeadByte[MAXIMUM_LEADBYTES]; +}; +static_assert(sizeof(NLS_FILE_HEADER) == 26, "Wrong size for NLS_FILE_HEADER"); +#pragma pack(pop) + +static std::istream& get_clean_line(std::istream& stream, std::string& str) +{ + do + { + std::istream& ret = std::getline(stream, str); + if (!ret) + return ret; + + /* Ignore comments */ + std::size_t comment_pos = str.find_first_of(';'); + if (comment_pos != std::string::npos) + { + str.erase(comment_pos); + } + + /* Remove trailing spaces */ + std::size_t end_of_line = str.find_last_not_of(whitespaces); + if (end_of_line != std::string::npos) + str.erase(end_of_line + 1); + else + str.clear(); + + line_number++; + } while (str.empty()); + + return stream; +} + +static void tokenize(std::string& str, std::string& token) +{ + std::size_t token_start = str.find_first_not_of(whitespaces); + if (token_start == std::string::npos) + { + token = ""; + str.clear(); + return; + } + + std::size_t token_end = str.find_first_of(whitespaces, token_start); + if (token_end == std::string::npos) + { + token = str.substr(token_start); + str.clear(); + return; + } + + token = str.substr(token_start, token_end); + str.erase(0, str.find_first_not_of(whitespaces, token_end)); +} + +template<typename T> +static void tokenize(std::string& str, T& int_token, int base = 0) +{ + std::string token; + tokenize(str, token); + + long val; + val = std::stol(token, nullptr, base); + if ((val > std::numeric_limits<T>::max()) || (val < std::numeric_limits<T>::min())) + throw std::invalid_argument(token + " does not fit range [" + + std::to_string(std::numeric_limits<T>::min()) + ":" + std::to_string(std::numeric_limits<T>::max()) + "]"); + + int_token = val; +} + +void error(const std::string& err) +{ + std::cerr << "Error parsing line " << line_number <<": " << err << std::endl; + std::exit(1); +} + +int main(int argc, char* argv[]) +{ + if (argc != 3) + { + std::cerr << "Usage: " << argv[0] << " <txt_in> <nls_out>" << std::endl; + return 1; + } + + std::ifstream input(argv[1]); + if (!input.is_open()) + { + std::cerr << "Unable to open " << argv[1] << std::endl; + return 1; + } + + NLS_FILE_HEADER FileHeader; + memset(&FileHeader, 0, sizeof(FileHeader)); + + std::string curr_line; + // Get code page + if (!get_clean_line(input, curr_line)) + { + std::cerr << "ERROR: File is empty" << std::endl; + return 1; + } + + std::string token; + tokenize(curr_line, token); + if (token != "CODEPAGE") + error("expected CODEPAGE, got "" + token + "" instead"); + try + { + tokenize(curr_line, FileHeader.CodePage, 10); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + + if (!curr_line.empty()) + error("Garbage after CODEPAGE statement: "" + curr_line + """); + + /* Get CPINFO */ + if (!get_clean_line(input, curr_line)) + error("Nothing after CODEPAGE statement"); + + tokenize(curr_line, token); + if (token != "CPINFO") + error("Expected CPINFO, got "" + token + "" instead"); + try + { + tokenize(curr_line, FileHeader.MaximumCharacterSize); + tokenize(curr_line, FileHeader.DefaultChar); + tokenize(curr_line, FileHeader.UniDefaultChar); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + return 1; + } + if (!curr_line.empty()) + error("Garbage after CPINFO statement: "" + curr_line + """); + if ((FileHeader.MaximumCharacterSize != 1) && (FileHeader.MaximumCharacterSize != 2)) + error("Expected 1 or 2 as max char size in CPINFO, got "" + std::to_string(FileHeader.MaximumCharacterSize) + "" instead"); + if ((FileHeader.MaximumCharacterSize == 1) && (FileHeader.DefaultChar > std::numeric_limits<uint8_t>::max())) + error("Default MB character " + std::to_string(FileHeader.DefaultChar) + " doesn't fit in a 8-bit value"); + + /* Setup tables & default values */ + bool has_mbtable = false; + uint16_t mb_table[256] = {0}; + + bool has_wctable = false; + uint8_t* wc_table = new uint8_t[65536 * FileHeader.MaximumCharacterSize]; + if (FileHeader.MaximumCharacterSize == 1) + { + for (int i = 0; i < 65536; i++) + wc_table[i] = FileHeader.DefaultChar; + } + else + { + uint16_t* wc_table_dbcs = reinterpret_cast<uint16_t*>(wc_table); + for (int i = 0; i < 65536; i++) + wc_table_dbcs[i] = FileHeader.DefaultChar; + } + + std::vector<uint16_t> dbcs_table; + uint16_t lb_offsets[256] = {0}; + uint16_t dbcs_range_count = 0; + + uint16_t glyph_table[256] = {0}; + bool has_glyphs = false; + + /* Now parse */ + while (get_clean_line(input, curr_line)) + { + tokenize(curr_line, token); + + if (token == "ENDCODEPAGE") + { + if (!curr_line.empty()) + error("Garbage after ENDCODEPAGE statement: "" + curr_line + """); + break; + } + else if (token == "MBTABLE") + { + uint16_t table_size; + try + { + tokenize(curr_line, table_size); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (has_mbtable) + error("MBTABLE can only be declared once"); + if (table_size > 256) + error("MBTABLE size can't be larger than 256"); + if (!curr_line.empty()) + error("Garbage after MBTABLE statement: "" + curr_line + """); + + has_mbtable = true; + while (table_size--) + { + if (!get_clean_line(input, curr_line)) + error("Expected " + std::to_string(table_size + 1) + " more lines after MBTABLE token"); + + uint8_t mb; + uint16_t wc; + + try + { + tokenize(curr_line, mb); + tokenize(curr_line, wc); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after MBTABLE entry: "" + curr_line + """); + mb_table[mb] = wc; + } + } + else if (token == "WCTABLE") + { + uint32_t table_size; + try + { + tokenize(curr_line, table_size); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (has_wctable) + error("WCTABLE can only be declared once"); + if (!curr_line.empty()) + error("Garbage after WCTABLE statement: "" + curr_line + """); + if (table_size > 65536) + error("WCTABLE size can't be larger than 65536"); + + has_wctable = true; + + if (FileHeader.MaximumCharacterSize == 1) + { + while (table_size--) + { + if (!get_clean_line(input, curr_line)) + error("Expected " + std::to_string(table_size + 1) + " more lines after WCTABLE token"); + + uint8_t mb; + uint16_t wc; + + try + { + tokenize(curr_line, wc); + tokenize(curr_line, mb); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after WCTABLE entry: "" + curr_line + """); + wc_table[wc] = mb; + } + } + else + { + uint16_t* wc_table_dbcs = reinterpret_cast<uint16_t*>(wc_table); + while (table_size--) + { + if (!get_clean_line(input, curr_line)) + error("Expected " + std::to_string(table_size + 1) + " more lines after WCTABLE token"); + uint16_t mb; + uint16_t wc; + + try + { + tokenize(curr_line, wc); + tokenize(curr_line, mb); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after MBTABLE entry: "" + curr_line + """); + wc_table_dbcs[wc] = mb; + } + } + } + else if (token == "DBCSRANGE") + { + if (dbcs_range_count != 0) + error("DBCSRANGE can only be declared once"); + + try + { + tokenize(curr_line, dbcs_range_count); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (dbcs_range_count > (MAXIMUM_LEADBYTES / 2)) + error("DBCSRANGE count can't exceed " + std::to_string(MAXIMUM_LEADBYTES / 2)); + if (!curr_line.empty()) + error("Garbage after DBCSRANGE token"); + + std::size_t current_offset = 0; + + uint16_t range_count = dbcs_range_count; + uint16_t current_range = 0; + while (range_count--) + { + if (!get_clean_line(input, curr_line)) + error("Expected new range after DBCSRANGE"); + + uint8_t RangeStart, RangeEnd; + try + { + tokenize(curr_line, RangeStart); + tokenize(curr_line, RangeEnd); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after DBCS range declaration"); + + if (RangeStart > RangeEnd) + error("Invalid range specified for DBCSRANGE"); + + FileHeader.LeadByte[current_range*2] = RangeStart; + FileHeader.LeadByte[current_range*2+1] = RangeEnd; + current_range++; + + dbcs_table.resize(dbcs_table.size() + 256 * (RangeEnd - RangeStart + 1), FileHeader.UniDefaultChar); + + for (uint8_t LeadByte = RangeStart; LeadByte <= RangeEnd; LeadByte++) + { + if (!get_clean_line(input, curr_line)) + error("Expected new DBCSTABLE after DBCS range declaration"); + + tokenize(curr_line, token); + if (token != "DBCSTABLE") + error("Expected new DBCSTABLE after DBCS range declaration"); + + uint16_t table_size; + try + { + tokenize(curr_line, table_size); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (table_size > 256) + error("DBCSTABLE can't have more than 256 entries"); + while (table_size--) + { + if (!get_clean_line(input, curr_line)) + error("Expected " + std::to_string(table_size + 1) + " more lines after DBCSTABLE token"); + + uint8_t mb; + uint16_t wc; + + try + { + tokenize(curr_line, mb); + tokenize(curr_line, wc); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after DBCSTABLE entry: "" + curr_line + """); + + dbcs_table[current_offset + mb] = wc; + } + current_offset += 256; + /* Offsets start at 256 for the offset table. */ + lb_offsets[LeadByte] = current_offset; + } + } + } + else if (token == "GLYPHTABLE") + { + uint16_t table_size; + try + { + tokenize(curr_line, table_size); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (has_glyphs) + error("GLYPHTABLE can only be declared once"); + if (table_size > 256) + error("GLYPHTABLE size can't be larger than 256"); + if (!curr_line.empty()) + error("Garbage after GLYPHTABLE statement: "" + curr_line + """); + has_glyphs = true; + + while (table_size--) + { + if (!get_clean_line(input, curr_line)) + error("Expected " + std::to_string(table_size + 1) + " more lines after GLYPHTABLE token"); + + uint8_t mb; + uint16_t wc; + + try + { + tokenize(curr_line, mb); + tokenize(curr_line, wc); + } + catch(const std::invalid_argument& ia) + { + error(ia.what()); + } + if (!curr_line.empty()) + error("Garbage after GLYPHTABLE entry: "" + curr_line + """); + glyph_table[mb] = wc; + } + } + else + { + error("Unexpected token "" + token + """); + } + } + + if (token != "ENDCODEPAGE") + error("Expected last token to be "ENDCODEPAGE""); + + input.close(); + + /* Ensure this is minimally workable */ + if (!has_mbtable) + error("File has no MBTABLE statement"); + if (!has_wctable) + error("File has no WCTABLE statement"); + + /* Glyph table fixup */ + if (has_glyphs) + { + for(int i = 0; i < 256; i++) + { + if (glyph_table[i] == 0) + glyph_table[i] = mb_table[i]; + } + } + + /* Translated default char fixup */ + if (FileHeader.MaximumCharacterSize == 1) + { + FileHeader.TransDefaultChar = mb_table[FileHeader.DefaultChar]; + FileHeader.TransUniDefaultChar = wc_table[FileHeader.UniDefaultChar]; + } + else + { + if (FileHeader.DefaultChar > 0xFF) + { + uint16_t offset = lb_offsets[FileHeader.DefaultChar >> 8]; + if (!offset) + error("Default MB char is not translatable!"); + FileHeader.TransDefaultChar = dbcs_table[(FileHeader.DefaultChar & 0xFF) + (offset - 256)]; + } + else + { + FileHeader.TransDefaultChar = mb_table[FileHeader.DefaultChar]; + } + uint16_t* wc_table_dbcs = reinterpret_cast<uint16_t*>(wc_table); + FileHeader.TransUniDefaultChar = wc_table_dbcs[FileHeader.UniDefaultChar]; + } + FileHeader.HeaderSize = sizeof(NLS_FILE_HEADER) / sizeof(uint16_t); + + std::ofstream output(argv[2], std::ios_base::binary); + + output.write(reinterpret_cast<char*>(&FileHeader), sizeof(FileHeader)); + + uint16_t wc_table_offset = sizeof(mb_table) / sizeof(uint16_t) + + 1 /* size of glyph table */ + + (has_glyphs ? 256 : 0) /* Glyph table */ + + 1 /* Number of DBCS LeadByte ranges */ + + (dbcs_range_count ? 256 : 0) /* offsets of lead byte sub tables */ + + dbcs_table.size() /* LeadByte sub tables */ + + 1; /* Unknown flag */ + + output.write(reinterpret_cast<char*>(&wc_table_offset), sizeof(wc_table_offset)); + + output.write(reinterpret_cast<char*>(mb_table), sizeof(mb_table)); + + uint16_t glyph_table_size = has_glyphs ? 256 : 0; + output.write(reinterpret_cast<char*>(&glyph_table_size), sizeof(glyph_table_size)); + if (has_glyphs) + output.write(reinterpret_cast<char*>(glyph_table), sizeof(glyph_table)); + + output.write(reinterpret_cast<char*>(&dbcs_range_count), sizeof(dbcs_range_count)); + if (dbcs_range_count) + { + output.write(reinterpret_cast<char*>(lb_offsets), sizeof(lb_offsets)); + } + if (dbcs_table.size()) + { + output.write(reinterpret_cast<char*>(dbcs_table.data()), dbcs_table.size() * sizeof(uint16_t)); + } + + uint16_t unknown_flag = FileHeader.MaximumCharacterSize == 1 ? 0 : 4; + output.write(reinterpret_cast<char*>(&unknown_flag), sizeof(unknown_flag)); + + output.write(reinterpret_cast<char*>(wc_table), 65536 * FileHeader.MaximumCharacterSize); + + output.close(); + delete wc_table; + + return 0; +} diff --git a/sdk/tools/txt2nls/nls.c b/sdk/tools/txt2nls/nls.c deleted file mode 100644 index 02d84bab89a..00000000000 --- a/sdk/tools/txt2nls/nls.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * PROJECT: ReactOS TXT to NLS Converter - * LICENSE: GNU General Public License Version 2.0 or any later version - * FILE: devutils/txt2nls/nls.c - * COPYRIGHT: Copyright 2016 Dmitry Chapyshev dmitry@reactos.org - */ - -#include "precomp.h" - -#define _NLS_DEBUG_PRINT - -#ifdef _NLS_DEBUG_PRINT - -static void -nls_print_header(NLS_FILE_HEADER *header) -{ - uint32_t i; - - printf("HEADER:\n"); - printf("CodePage: %u\n", header->CodePage); - printf("Character size: %u\n", header->MaximumCharacterSize); - printf("Default char: 0x%02X\n", header->DefaultChar); - printf("Default unicode char: 0x%04X\n", header->UniDefaultChar); - printf("Trans default char: 0x%02X\n", header->TransUniDefaultChar); - printf("Trans default unicode char: 0x%04X\n", header->TransUniDefaultChar); - - for (i = 0; i < MAXIMUM_LEADBYTES; i++) - { - printf("LeadByte[%u] = 0x%02X\n", i, header->LeadByte[i]); - } - - printf("\n"); -} - -static void -nls_print_mb_table(uint16_t *mb_table, uint16_t uni_default_char) -{ - uint32_t ch; - - printf("MBTABLE:\n"); - - for (ch = 0; ch <= 0xFF; ch++) - { - if (mb_table[ch] != uni_default_char) - { - printf("0x%02X 0x%04X\n", (unsigned int)ch, (unsigned int)mb_table[ch]); - } - } - - printf("\n"); -} - -static void -nls_print_wc_table(uint16_t *wc_table, uint16_t default_char, int is_dbcs) -{ - uint32_t ch; - - printf("WCTABLE:\n"); - - for (ch = 0; ch <= 0xFFFF; ch++) - { - /* DBCS code page */ - if (is_dbcs) - { - uint16_t *table = (uint16_t*)wc_table; - - if (table[ch] != default_char) - printf("0x%04X 0x%04X\n", (unsigned int)ch, (unsigned int)table[ch]); - } - /* SBCS code page */ - else - { - uint8_t *table = (uint8_t*)wc_table; - - if (table[ch] != default_char) - printf("0x%04X 0x%02X\n", (unsigned int)ch, (unsigned int)table[ch]); - } - } - - printf("\n"); -} - -static void -nls_print_glyph_table(uint16_t *glyph_table, uint16_t uni_default_char) -{ - uint32_t ch; - - printf("GLYPHTABLE:\n"); - - for (ch = 0; ch <= 0xFF; ch++) - { - if (glyph_table[ch] != uni_default_char) - { - printf("0x%02X 0x%04X\n", (unsigned int)ch, (unsigned int)glyph_table[ch]); - } - } - - printf("\n"); -} - -#endif /* _NLS_DEBUG_PRINT */ - -int -nls_from_txt(const char *txt_file_path, const char *nls_file_path) -{ - NLS_FILE_HEADER header; - FILE *file = NULL; - uint16_t *mb_table = NULL; - uint16_t *wc_table = NULL; - uint16_t *glyph_table = NULL; - uint16_t number_of_lb_ranges; - uint16_t size; - int is_dbcs; - int res = 0; - - memset(&header, 0, sizeof(header)); - - if (!txt_get_header(txt_file_path, &header)) - goto Cleanup; - - is_dbcs = (header.MaximumCharacterSize == 2) ? 1 : 0; - - mb_table = txt_get_mb_table(txt_file_path, header.UniDefaultChar); - if (!mb_table) - goto Cleanup; - - wc_table = txt_get_wc_table(txt_file_path, header.DefaultChar, is_dbcs); - if (!wc_table) - goto Cleanup; - - /* GLYPHTABLE optionally. We do not leave if it is absent */ - glyph_table = txt_get_glyph_table(txt_file_path, header.UniDefaultChar); - - if (is_dbcs) - { - /* DBCS codepage */ - uint16_t *table = (uint16_t*)wc_table; - header.TransUniDefaultChar = table[header.UniDefaultChar]; - /* TODO: TransDefaultChar for DBCS codepages */ - } - else - { - /* SBCS codepage */ - uint8_t *table = (uint8_t*)wc_table; - header.TransUniDefaultChar = table[header.UniDefaultChar]; - header.TransDefaultChar = mb_table[LOBYTE(header.DefaultChar)]; - } - -#ifdef _NLS_DEBUG_PRINT - nls_print_header(&header); - nls_print_mb_table(mb_table, header.UniDefaultChar); - if (glyph_table) - nls_print_glyph_table(glyph_table, header.UniDefaultChar); - nls_print_wc_table(wc_table, header.DefaultChar, is_dbcs); -#endif /* _NLS_DEBUG_PRINT */ - - /* Create binary file with write access */ - file = fopen(nls_file_path, "wb"); - if (!file) - { - printf("Unable to create NLS file.\n"); - goto Cleanup; - } - - /* Write NLS file header */ - if (fwrite(&header, 1, sizeof(header), file) != sizeof(header)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - size = (256 * sizeof(uint16_t)) + /* Primary CP to Unicode table */ - sizeof(uint16_t) + /* optional OEM glyph table size in words */ - (glyph_table ? (256 * sizeof(uint16_t)) : 0) + /* OEM glyph table size in words * sizeof(uint16_t) */ - sizeof(uint16_t) + /* Number of DBCS LeadByte ranges */ - 0 + /* offsets of lead byte sub tables */ - 0 + /* LeadByte sub tables */ - sizeof(uint16_t); /* Unknown flag */ - - size /= sizeof(uint16_t); - - if (fwrite(&size, 1, sizeof(size), file) != sizeof(size)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - /* Write multibyte table */ - if (fwrite(mb_table, 1, (256 * sizeof(uint16_t)), file) != (256 * sizeof(uint16_t))) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - /* OEM glyph table size in words */ - size = (glyph_table ? 256 : 0); - - if (fwrite(&size, 1, sizeof(size), file) != sizeof(size)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - if (glyph_table) - { - /* Write OEM glyph table */ - if (fwrite(glyph_table, 1, (256 * sizeof(uint16_t)), file) != (256 * sizeof(uint16_t))) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - } - - /* Number of DBCS LeadByte ranges */ - number_of_lb_ranges = 0; - if (fwrite(&number_of_lb_ranges, 1, sizeof(number_of_lb_ranges), file) != sizeof(number_of_lb_ranges)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - /* Unknown flag */ - size = 0; - if (fwrite(&size, 1, sizeof(size), file) != sizeof(size)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - /* Write wide char table */ - if (fwrite(wc_table, 1, (65536 * header.MaximumCharacterSize), file) != (65536 * header.MaximumCharacterSize)) - { - printf("Unable to write NLS file.\n"); - goto Cleanup; - } - - res = 1; - -Cleanup: - if (file) fclose(file); - free(mb_table); - free(wc_table); - free(glyph_table); - - return res; -} diff --git a/sdk/tools/txt2nls/precomp.h b/sdk/tools/txt2nls/precomp.h deleted file mode 100644 index 7c6ee49b337..00000000000 --- a/sdk/tools/txt2nls/precomp.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * PROJECT: ReactOS TXT to NLS Converter - * LICENSE: GNU General Public License Version 2.0 or any later version - * FILE: devutils/txt2nls/precomp.h - * COPYRIGHT: Copyright 2016 Dmitry Chapyshev dmitry@reactos.org - */ - -#ifndef __PRECOMP_H -#define __PRECOMP_H - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <ctype.h> -#include <memory.h> - -#define LOBYTE(w) ((uint8_t)((uint32_t)(w) & 0xff)) - -#define MAXIMUM_LEADBYTES 12 - -typedef struct -{ - uint16_t HeaderSize; - uint16_t CodePage; - uint16_t MaximumCharacterSize; - uint16_t DefaultChar; - uint16_t UniDefaultChar; - uint16_t TransDefaultChar; - uint16_t TransUniDefaultChar; - uint8_t LeadByte[MAXIMUM_LEADBYTES]; -} NLS_FILE_HEADER; - -/* nls.c */ -int -nls_from_txt(const char *txt_file_path, const char *nls_file_path); - -/* bestfit.c */ -int -txt_get_header(const char *file_path, NLS_FILE_HEADER *header); - -uint16_t* -txt_get_mb_table(const char *file_path, uint16_t uni_default_char); - -uint16_t* -txt_get_wc_table(const char *file_path, uint16_t default_char, int is_dbcs); - -uint16_t* -txt_get_glyph_table(const char *file_path, uint16_t uni_default_char); - -#endif diff --git a/sdk/tools/txt2nls/txt.c b/sdk/tools/txt2nls/txt.c deleted file mode 100644 index abf4dd2c37c..00000000000 --- a/sdk/tools/txt2nls/txt.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - * PROJECT: ReactOS TXT to NLS Converter - * LICENSE: GNU General Public License Version 2.0 or any later version - * FILE: devutils/txt2nls/txt.c - * COPYRIGHT: Copyright 2016 Dmitry Chapyshev dmitry@reactos.org - */ - -#include "precomp.h" - -int -txt_get_header(const char *file_path, NLS_FILE_HEADER *header) -{ - FILE *file; - char *p; - char buf[256]; - uint32_t line = 0; - int res = 0; - int found; - uint32_t val; - - file = fopen(file_path, "r"); - if (!file) - { - printf("Unable to read TXT file.\n"); - return 0; - } - - /* Find CODEPAGE entry */ - found = 0; - while (fgets(buf, sizeof(buf), file)) - { - ++line; - - p = strstr(buf, "CODEPAGE"); - if (p) - { - /* Length of CODEPAGE string is 8 chars */ - p += 8; - - /* Skip all spaces after CODEPAGE */ - while (isspace(*p)) ++p; - - /* Convert string to uint32_t */ - val = strtoul(p, &p, 10); - - /* Validate codepage value */ - if (val > 0xFFFF) - { - printf("Wrong codepage: %u (line: %u)\n", val, line); - goto Cleanup; - } - - header->CodePage = (uint16_t)val; - - found = 1; - break; - } - } - - if (!found) - { - printf("CODEPAGE not found.\n"); - goto Cleanup; - } - - /* Find CPINFO entry */ - found = 0; - while (fgets(buf, sizeof(buf), file)) - { - ++line; - - p = strstr(buf, "CPINFO"); - if (p) - { - /* Length of CPINFO string is 6 chars */ - p += 6; - - /* Skip all spaces after CPINFO */ - while (isspace(*p)) ++p; - - /* Convert string to uint32_t */ - val = strtoul(p, &p, 10); - - /* Validate value */ - if (val != 1 && val != 2) - { - printf("Wrong character size: %u (line: %u)\n", val, line); - goto Cleanup; - } - - header->MaximumCharacterSize = (uint16_t)val; - - /* Skip all spaces after character size */ - while (isspace(*p)) ++p; - - /* Convert string to uint32_t */ - val = strtoul(p, &p, 16); - header->DefaultChar = (uint16_t)val; - /* By default set value as DefaultChar */ - header->TransDefaultChar = (uint16_t)val; - - /* Skip all spaces after default char */ - while (isspace(*p)) ++p; - - /* Convert string to uint32_t */ - val = strtoul(p, &p, 16); - header->UniDefaultChar = (uint16_t)val; - /* By default set value as UniDefaultChar */ - header->TransUniDefaultChar = (uint16_t)val; - - found = 1; - break; - } - } - - if (!found) - { - printf("CPINFO not found.\n"); - goto Cleanup; - } - - header->HeaderSize = sizeof(NLS_FILE_HEADER) / sizeof(uint16_t); - - res = 1; - -Cleanup: - fclose(file); - - return res; -} - -uint16_t* -txt_get_mb_table(const char *file_path, uint16_t uni_default_char) -{ - uint16_t *table; - char buf[256]; - char *p; - uint32_t count = 0; - uint32_t index; - uint32_t line = 0; - int found; - int res = 0; - FILE *file; - - table = malloc(256 * sizeof(uint16_t)); - if (!table) - { - printf("Memory allocation failure\n"); - return NULL; - } - - /* Set default value for all table items */ - for (index = 0; index <= 255; index++) - table[index] = uni_default_char; - - file = fopen(file_path, "r"); - if (!file) - { - printf("Unable to read TXT file.\n"); - goto Cleanup; - } - - /* Find MBTABLE entry */ - found = 0; - while (fgets(buf, sizeof(buf), file)) - { - ++line; - - p = strstr(buf, "MBTABLE"); - if (p) - { - p += 7; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - count = strtoul(p, &p, 10); - if (count == 0 || count > 256) - { - printf("Wrong MBTABLE size: %u (line: %u)\n", count, line); - goto Cleanup; - } - - found = 1; - break; - } - } - - if (!found) - { - printf("MBTABLE not found.\n"); - goto Cleanup; - } - - /* Parse next line */ - while (fgets(buf, sizeof(buf), file) && count) - { - uint32_t cp_char; - uint32_t uni_char; - - ++line; - - p = buf; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - if (!*p || p[0] == ';') - continue; - - cp_char = strtoul(p, &p, 16); - if (cp_char > 0xFF) - { - printf("Wrong char value: %u (line: %u)\n", cp_char, line); - goto Cleanup; - } - - /* Skip spaces */ - while (isspace(*p)) ++p; - - uni_char = strtoul(p, &p, 16); - if (uni_char > 0xFFFF) - { - printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line); - goto Cleanup; - } - - table[cp_char] = uni_char; - --count; - } - - res = 1; - -Cleanup: - if (!res) - { - free(table); - table = NULL; - } - - fclose(file); - - return table; -} - -uint16_t* -txt_get_wc_table(const char *file_path, uint16_t default_char, int is_dbcs) -{ - char buf[256]; - char *p; - uint16_t *table; - uint32_t index; - uint32_t count = 0; - uint32_t line = 0; - int res = 0; - int found; - FILE *file; - - table = malloc(65536 * (is_dbcs ? sizeof(uint16_t) : sizeof(uint8_t))); - if (!table) - { - printf("Memory allocation failure\n"); - return NULL; - } - - /* Set default value for all table items */ - for (index = 0; index <= 65535; index++) - { - /* DBCS code page */ - if (is_dbcs) - { - uint16_t *tmp = (uint16_t*)table; - tmp[index] = default_char; - } - /* SBCS code page */ - else - { - uint8_t *tmp = (uint8_t*)table; - tmp[index] = default_char; - } - } - - file = fopen(file_path, "r"); - if (!file) - { - printf("Unable to read TXT file.\n"); - goto Cleanup; - } - - /* Find WCTABLE entry */ - found = 0; - while (fgets(buf, sizeof(buf), file)) - { - ++line; - - p = strstr(buf, "WCTABLE"); - if (p) - { - p += 7; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - count = strtoul(p, &p, 10); - if (count == 0 || count > 65536) - { - printf("Wrong WCTABLE size: %u (line: %u)\n", count, line); - goto Cleanup; - } - - found = 1; - break; - } - } - - if (!found) - { - printf("WCTABLE not found.\n"); - goto Cleanup; - } - - /* Parse next line */ - while (fgets(buf, sizeof(buf), file) && count) - { - uint32_t cp_char; - uint32_t uni_char; - - ++line; - - p = buf; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - if (!*p || p[0] == ';') - continue; - - uni_char = strtoul(p, &p, 16); - if (uni_char > 0xFFFF) - { - printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line); - goto Cleanup; - } - - /* Skip spaces */ - while (isspace(*p)) ++p; - - cp_char = strtoul(p, &p, 16); - if ((is_dbcs && cp_char > 0xFFFF) || (!is_dbcs && cp_char > 0xFF)) - { - printf("Wrong char value: %u (line: %u)\n", cp_char, line); - goto Cleanup; - } - - /* DBCS code page */ - if (is_dbcs) - { - uint16_t *tmp = (uint16_t*)table; - tmp[uni_char] = cp_char; - } - /* SBCS code page */ - else - { - uint8_t *tmp = (uint8_t*)table; - tmp[uni_char] = cp_char; - } - - --count; - } - - res = 1; - -Cleanup: - if (!res) - { - free(table); - table = NULL; - } - - fclose(file); - - return table; -} - -uint16_t* -txt_get_glyph_table(const char *file_path, uint16_t uni_default_char) -{ - uint16_t *table; - char buf[256]; - char *p; - uint32_t count = 0; - uint32_t index; - uint32_t line = 0; - int found; - int res = 0; - FILE *file; - - table = malloc(256 * sizeof(uint16_t)); - if (!table) - { - printf("Memory allocation failure\n"); - return NULL; - } - - /* Set default value for all table items */ - for (index = 0; index <= 255; index++) - table[index] = uni_default_char; - - file = fopen(file_path, "r"); - if (!file) - { - printf("Unable to read TXT file.\n"); - goto Cleanup; - } - - /* Find GLYPHTABLE entry */ - found = 0; - while (fgets(buf, sizeof(buf), file)) - { - ++line; - - p = strstr(buf, "GLYPHTABLE"); - if (p) - { - p += 10; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - count = strtoul(p, &p, 10); - if (count == 0 || count > 256) - { - printf("Wrong GLYPHTABLE size: %u (line: %u)\n", count, line); - goto Cleanup; - } - - found = 1; - break; - } - } - - if (!found) - { - printf("GLYPHTABLE not found.\n"); - goto Cleanup; - } - - /* Parse next line */ - while (fgets(buf, sizeof(buf), file) && count) - { - uint32_t cp_char; - uint32_t uni_char; - - ++line; - - p = buf; - - /* Skip spaces */ - while (isspace(*p)) ++p; - - if (!*p || p[0] == ';') - continue; - - cp_char = strtoul(p, &p, 16); - if (cp_char > 0xFF) - { - printf("Wrong char value: %u (line: %u)\n", cp_char, line); - goto Cleanup; - } - - /* Skip spaces */ - while (isspace(*p)) ++p; - - uni_char = strtoul(p, &p, 16); - if (uni_char > 0xFFFF) - { - printf("Wrong unicode char value: %u (line: %u)\n", uni_char, line); - goto Cleanup; - } - - table[cp_char] = uni_char; - --count; - } - - res = 1; - -Cleanup: - if (!res) - { - free(table); - table = NULL; - } - - fclose(file); - - return table; -}