https://git.reactos.org/?p=reactos.git;a=commitdiff;h=79b2d9c2ff53237f79765…
commit 79b2d9c2ff53237f7976533d788a710a1738a40a
Author: Jérôme Gardou <jerome.gardou(a)reactos.org>
AuthorDate: Tue May 18 17:10:41 2021 +0200
Commit: Jérôme Gardou <zefklop(a)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(a)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(a)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(a)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(a)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(a)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;
-}