https://git.reactos.org/?p=reactos.git;a=commitdiff;h=79b2d9c2ff53237f7976533d788a710a1738a40a

commit 79b2d9c2ff53237f7976533d788a710a1738a40a
Author:     Jérôme Gardou <[email protected]>
AuthorDate: Tue May 18 17:10:41 2021 +0200
Commit:     Jérôme Gardou <[email protected]>
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 <[email protected]>
- */
-
-#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 <[email protected]>
+ */
+
+#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 <[email protected]>
- */
-
-#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 <[email protected]>
- */
-
-#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 <[email protected]>
- */
-
-#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;
-}

Reply via email to