This is an automated email from the git hooks/post-receive script.

odyx pushed a commit to branch debian/master
in repository colobot.

commit c03dfc12848682fd0083f19706239381c659d991
Author: melex750 <melex...@users.noreply.github.com>
Date:   Sat Jul 22 14:29:05 2017 -0400

    Add escape codes for string literals
---
 po/colobot.pot                           |  18 ++++
 po/de.po                                 |  18 ++++
 po/fr.po                                 |  18 ++++
 po/pl.po                                 |  18 ++++
 po/ru.po                                 |  18 ++++
 src/CBot/CBotEnums.h                     |   6 ++
 src/CBot/CBotInstr/CBotExprLitString.cpp | 144 ++++++++++++++++++++++++++++---
 src/CBot/CBotInstr/CBotExprLitString.h   |   3 +
 src/CBot/CBotToken.cpp                   |  25 ++----
 src/CBot/CBotUtils.cpp                   |  45 ++++++++++
 src/CBot/CBotUtils.h                     |  15 ++++
 src/common/restext.cpp                   |   6 ++
 test/unit/CBot/CBot_test.cpp             | 114 ++++++++++++++++++++++++
 13 files changed, 417 insertions(+), 31 deletions(-)

diff --git a/po/colobot.pot b/po/colobot.pot
index 509a3c7..419b88e 100644
--- a/po/colobot.pot
+++ b/po/colobot.pot
@@ -1770,6 +1770,24 @@ msgstr ""
 msgid "This parameter needs a default value"
 msgstr ""
 
+msgid "Missing end quote"
+msgstr ""
+
+msgid "Unknown escape sequence"
+msgstr ""
+
+msgid "Octal value out of range"
+msgstr ""
+
+msgid "Missing hex digits after escape sequence"
+msgstr ""
+
+msgid "Hex value out of range"
+msgstr ""
+
+msgid "Invalid universal character name"
+msgstr ""
+
 msgid "Dividing by zero"
 msgstr ""
 
diff --git a/po/de.po b/po/de.po
index 5e2f4a5..1c839a0 100644
--- a/po/de.po
+++ b/po/de.po
@@ -680,6 +680,9 @@ msgstr "Anweisungen über das ausgewählte Objekt"
 msgid "Help balloons\\Explain the function of the buttons"
 msgstr "Hilfeblasen\\Hilfeblasen"
 
+msgid "Hex value out of range"
+msgstr ""
+
 #, fuzzy
 msgid "Higher speed\\Doubles speed"
 msgstr "Geschwindigkeit 2.0x\\Spielgeschwindigkeit doppelt so schnell"
@@ -759,6 +762,9 @@ msgstr "Anweisungen\\Anweisungen für die Mission oder Übung"
 msgid "Internal error - tell the developers"
 msgstr "Interner Fehler - Benachrichtige bitte die Entwickler"
 
+msgid "Invalid universal character name"
+msgstr ""
+
 msgid "Invert\\Invert values on this axis"
 msgstr "Invertieren\\Die Werte dieser Achse invertieren"
 
@@ -869,6 +875,12 @@ msgstr "Verkleinern"
 msgid "Mipmap level\\Mipmap level"
 msgstr "Mipmap-Level\\Mipmap-Level"
 
+msgid "Missing end quote"
+msgstr ""
+
+msgid "Missing hex digits after escape sequence"
+msgstr ""
+
 msgid "Mission name"
 msgstr "Name der Mission"
 
@@ -1031,6 +1043,9 @@ msgstr "OK\\Programm kompilieren"
 msgid "Object too close"
 msgstr "Gegenstand zu nahe"
 
+msgid "Octal value out of range"
+msgstr ""
+
 msgid "One step"
 msgstr "Ein Schritt"
 
@@ -1632,6 +1647,9 @@ msgstr "Das Objekt existiert nicht"
 msgid "Unknown command"
 msgstr "Befehl unbekannt"
 
+msgid "Unknown escape sequence"
+msgstr ""
+
 msgid "Unknown function"
 msgstr "Unbekannte Funktion"
 
diff --git a/po/fr.po b/po/fr.po
index 01ca9de..a287717 100644
--- a/po/fr.po
+++ b/po/fr.po
@@ -677,6 +677,9 @@ msgstr "Instructions sur la sélection"
 msgid "Help balloons\\Explain the function of the buttons"
 msgstr "Bulles d'aide\\Bulles explicatives"
 
+msgid "Hex value out of range"
+msgstr ""
+
 #, fuzzy
 msgid "Higher speed\\Doubles speed"
 msgstr "Vitesse 2.0x\\Deux fois plus rapide"
@@ -756,6 +759,9 @@ msgstr "Instructions mission\\Marche à suivre"
 msgid "Internal error - tell the developers"
 msgstr "Erreur interne - contacter les développeurs"
 
+msgid "Invalid universal character name"
+msgstr ""
+
 msgid "Invert\\Invert values on this axis"
 msgstr "Inversion\\Inverse les valeurs sur cet axe"
 
@@ -866,6 +872,12 @@ msgstr "Taille réduite"
 msgid "Mipmap level\\Mipmap level"
 msgstr "Niveau de MIP mapping\\Niveau de MIP mapping"
 
+msgid "Missing end quote"
+msgstr ""
+
+msgid "Missing hex digits after escape sequence"
+msgstr ""
+
 msgid "Mission name"
 msgstr "Nom de la mission"
 
@@ -1028,6 +1040,9 @@ msgstr "D'accord\\Compiler le programme"
 msgid "Object too close"
 msgstr "Objet trop proche"
 
+msgid "Octal value out of range"
+msgstr ""
+
 msgid "One step"
 msgstr "Un pas"
 
@@ -1629,6 +1644,9 @@ msgstr "Objet n'existe pas"
 msgid "Unknown command"
 msgstr "Commande inconnue"
 
+msgid "Unknown escape sequence"
+msgstr ""
+
 msgid "Unknown function"
 msgstr "Routine inconnue"
 
diff --git a/po/pl.po b/po/pl.po
index 07a6328..bb28851 100644
--- a/po/pl.po
+++ b/po/pl.po
@@ -678,6 +678,9 @@ msgstr "Pomoc na temat zaznaczonego obiektu"
 msgid "Help balloons\\Explain the function of the buttons"
 msgstr "Dymki pomocy\\Wyjaśnia funkcje przycisków"
 
+msgid "Hex value out of range"
+msgstr ""
+
 msgid "Higher speed\\Doubles speed"
 msgstr "Zwiększ prędkość\\Podwaja prędkość"
 
@@ -756,6 +759,9 @@ msgstr "Rozkazy\\Pokazuje rozkazy dotyczące bieżącej misji"
 msgid "Internal error - tell the developers"
 msgstr "Błąd wewnętrzny - powiadom twórców gry"
 
+msgid "Invalid universal character name"
+msgstr ""
+
 msgid "Invert\\Invert values on this axis"
 msgstr "Odwróć\\Odwróć wartości na tej osi"
 
@@ -852,6 +858,12 @@ msgstr "Pomniejsz"
 msgid "Mipmap level\\Mipmap level"
 msgstr "Poziom mipmap\\Poziom mipmap"
 
+msgid "Missing end quote"
+msgstr ""
+
+msgid "Missing hex digits after escape sequence"
+msgstr ""
+
 msgid "Mission name"
 msgstr "Nazwa misji"
 
@@ -1014,6 +1026,9 @@ msgstr "OK\\Zamyka edytor programu i powraca do gry"
 msgid "Object too close"
 msgstr "Obiekt za blisko"
 
+msgid "Octal value out of range"
+msgstr ""
+
 msgid "One step"
 msgstr "Jeden krok"
 
@@ -1614,6 +1629,9 @@ msgstr "Obiekt nieznany"
 msgid "Unknown command"
 msgstr "Nieznane polecenie"
 
+msgid "Unknown escape sequence"
+msgstr ""
+
 msgid "Unknown function"
 msgstr "Funkcja nieznana"
 
diff --git a/po/ru.po b/po/ru.po
index fdcf909..f2b2535 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -686,6 +686,9 @@ msgstr "Справка о выбранном объекте"
 msgid "Help balloons\\Explain the function of the buttons"
 msgstr "Подсказки\\Объяснение функций кнопок"
 
+msgid "Hex value out of range"
+msgstr ""
+
 #, fuzzy
 msgid "Higher speed\\Doubles speed"
 msgstr "Скорость 2.0х\\В два раза быстрее"
@@ -765,6 +768,9 @@ msgstr "Инструкции\\Показывает инструкции по т
 msgid "Internal error - tell the developers"
 msgstr "Внутренняя ошибка - сообщите разработчикам"
 
+msgid "Invalid universal character name"
+msgstr ""
+
 msgid "Invert\\Invert values on this axis"
 msgstr "Инвертир.\\Инвертировать значения по этой оси"
 
@@ -875,6 +881,12 @@ msgstr "Свернуть"
 msgid "Mipmap level\\Mipmap level"
 msgstr "Уровень уменьшающей фильтрации\\Уровень уменьшающей фильтрации"
 
+msgid "Missing end quote"
+msgstr ""
+
+msgid "Missing hex digits after escape sequence"
+msgstr ""
+
 msgid "Mission name"
 msgstr "Название миссии"
 
@@ -1039,6 +1051,9 @@ msgstr "ОК\\Закрыть редактор программ и вернуть
 msgid "Object too close"
 msgstr "Объект слишком близок"
 
+msgid "Octal value out of range"
+msgstr ""
+
 msgid "One step"
 msgstr "Один шаг"
 
@@ -1645,6 +1660,9 @@ msgstr "Неизвестный объект"
 msgid "Unknown command"
 msgstr "Неизвестная команда"
 
+msgid "Unknown escape sequence"
+msgstr ""
+
 msgid "Unknown function"
 msgstr "Неизвестная функция"
 
diff --git a/src/CBot/CBotEnums.h b/src/CBot/CBotEnums.h
index f98d4e9..fb701bc 100644
--- a/src/CBot/CBotEnums.h
+++ b/src/CBot/CBotEnums.h
@@ -241,6 +241,12 @@ enum CBotError : int
     CBotErrNoClassName   = 5046, //!< class name expected
     CBotErrNoReturn      = 5047, //!< non-void function needs "return;"
     CBotErrDefaultValue  = 5048, //!< this parameter needs a default value
+    CBotErrEndQuote      = 5049, //!< missing end quote
+    CBotErrBadEscape     = 5050, //!< unknown escape sequence
+    CBotErrOctalRange    = 5051, //!< octal value out of range
+    CBotErrHexDigits     = 5052, //!< missing hex digits after escape sequence
+    CBotErrHexRange      = 5053, //!< hex value out of range
+    CBotErrUnicodeName   = 5054, //!< invalid universal character name
 
     // Runtime errors
     CBotErrZeroDiv       = 6000, //!< division by zero
diff --git a/src/CBot/CBotInstr/CBotExprLitString.cpp 
b/src/CBot/CBotInstr/CBotExprLitString.cpp
index ad85f7a..58d5fe1 100644
--- a/src/CBot/CBotInstr/CBotExprLitString.cpp
+++ b/src/CBot/CBotInstr/CBotExprLitString.cpp
@@ -42,15 +42,136 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, 
CBotCStack* pStack)
 {
     CBotCStack* pStk = pStack->TokenStack();
 
-    CBotExprLitString* inst = new CBotExprLitString();
-
-    inst->SetToken(p);
-    p = p->GetNext();
-
-    CBotVar*    var = CBotVar::Create("", CBotTypString);
-    pStk->SetVar(var);
-
-    return pStack->Return(inst, pStk);
+    std::string s = p->GetString();
+
+    auto it = s.cbegin();
+    if (++it != s.cend())
+    {
+        int pos = p->GetStart();
+        std::string valstring = "";
+        while (it != s.cend() && *it != '\"')
+        {
+            pStk->SetStartError(++pos);
+            if (*it != '\\') // not escape sequence ?
+            {
+                valstring += *(it++);
+                continue;
+            }
+
+            if (++it == s.cend()) break;
+
+            if (CharInList(*it, "01234567"))          // octal
+            {
+                std::string octal = "";
+
+                for (int i = 0; i < 3; i++)
+                {
+                    if (!CharInList(*it, "01234567")) break;
+                    ++pos;
+                    octal += *it;
+                    if (++it == s.cend()) break;
+                }
+
+                unsigned int val = std::stoi(octal, nullptr, 8);
+                if (val <= 255)
+                {
+                    valstring.push_back(val);
+                    continue;
+                }
+                pStk->SetError(CBotErrOctalRange, pos + 1);
+            }
+            else
+            {
+                ++pos;
+                unsigned char c = *(it++);
+                if (c == '\"' || c == '\'' || c == '\\') valstring += c;
+                else if (c == 'a') valstring += '\a'; // alert bell
+                else if (c == 'b') valstring += '\b'; // backspace
+                else if (c == 'f') valstring += '\f'; // form feed
+                else if (c == 'n') valstring += '\n'; // new line
+                else if (c == 'r') valstring += '\r'; // carriage return
+                else if (c == 't') valstring += '\t'; // horizontal tab
+                else if (c == 'v') valstring += '\v'; // vertical tab
+                else if (c == 'x' || c == 'u' || c == 'U') // hex or unicode
+                {
+                    if (it != s.cend())
+                    {
+                        std::string hex = "";
+                        bool isHexCode = (c == 'x');
+                        size_t maxlen = (c == 'u') ? 4 : 8;
+
+                        for (size_t i = 0; isHexCode || i < maxlen; i++)
+                        {
+                            if (!CharInList(*it, "0123456789ABCDEFabcdef")) 
break;
+                            ++pos;
+                            hex += *it;
+                            if (++it == s.cend()) break;
+                        }
+
+                        if (!hex.empty())
+                        {
+                            unsigned int val = 0;
+                            try
+                            {
+                                val = std::stoi(hex, nullptr, 16);
+                            }
+                            catch (const std::out_of_range& e)
+                            {
+                                pStk->SetError(CBotErrHexRange, pos + 1);
+                            }
+
+                            if (pStk->IsOk())
+                            {
+                                if (isHexCode)        // hexadecimal
+                                {
+                                    if (val <= 255)
+                                    {
+                                        valstring.push_back(val);
+                                        continue;
+                                    }
+                                    pStk->SetError(CBotErrHexRange, pos + 1);
+                                }
+                                else if (maxlen == hex.length()) // unicode 
character
+                                {
+                                    if (val < 0xD800 || (0xDFFF < val && val < 
0x110000))
+                                    {
+                                        valstring += CodePointToUTF8(val);
+                                        continue;
+                                    }
+                                    pStk->SetError(CBotErrUnicodeName, pos + 
1);
+                                }
+                            }
+                        }
+                    }
+
+                    pStk->SetError(CBotErrHexDigits, pos + 1);
+                }
+                else
+                    pStk->SetError(CBotErrBadEscape, pos + 1);   // unknown 
escape code
+            }
+
+            if (!pStk->IsOk()) break;
+        }
+
+        if (it == s.cend() || *it != '\"')
+            pStk->SetError(CBotErrEndQuote, p);
+
+        if (pStk->IsOk())
+        {
+            CBotExprLitString* inst = new CBotExprLitString();
+            inst->m_valstring.swap(valstring);
+            inst->SetToken(p);
+            p = p->GetNext();
+
+            CBotVar* var = CBotVar::Create("", CBotTypString);
+            pStk->SetVar(var);
+
+            return pStack->Return(inst, pStk);
+        }
+    }
+
+    pStk->SetError(CBotErrEndQuote, p);
+    return pStack->Return(nullptr, pStk);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
@@ -62,10 +183,7 @@ bool CBotExprLitString::Execute(CBotStack* &pj)
 
     CBotVar*    var = CBotVar::Create("", CBotTypString);
 
-    std::string    chaine = m_token.GetString();
-    chaine = chaine.substr(1, chaine.length()-2);    // removes the quotes
-
-    var->SetValString(chaine);                    // value of the number
+    var->SetValString(m_valstring);
 
     pile->SetVar(var);                            // put on the stack
 
diff --git a/src/CBot/CBotInstr/CBotExprLitString.h 
b/src/CBot/CBotInstr/CBotExprLitString.h
index 4336dd1..55c3965 100644
--- a/src/CBot/CBotInstr/CBotExprLitString.h
+++ b/src/CBot/CBotInstr/CBotExprLitString.h
@@ -58,6 +58,9 @@ public:
 protected:
     virtual const std::string GetDebugName() override { return 
"CBotExprLitString"; }
     virtual std::string GetDebugData() override;
+
+private:
+    std::string m_valstring = "";
 };
 
 } // namespace CBot
diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp
index d9e33ff..3c4bc7d 100644
--- a/src/CBot/CBotToken.cpp
+++ b/src/CBot/CBotToken.cpp
@@ -241,23 +241,13 @@ void CBotToken::SetPos(int start, int end)
 }
 
 
////////////////////////////////////////////////////////////////////////////////
-bool CharInList(const char c, const char* list)
-{
-    int     i = 0;
-
-    while (true)
-    {
-        if (c == list[i++]) return true;
-        if (list[i] == 0) return false;
-    }
-}
 
-static char    sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.";
+static char    sep1[] = " \r\n\t,:()[]{}-+*/=;><!~^|&%.\"\'?";
 static char    sep2[] = " \r\n\t";                           // only separators
-static char    sep3[] = ",:()[]{}-+*/=;<>!~^|&%.";           // operational 
separators
+static char    sep3[] = ",:()[]{}-+*/=;<>!~^|&%.?";          // operational 
separators
 static char    num[]  = "0123456789";                        // point (single) 
is tested separately
 static char    hexnum[]   = "0123456789ABCDEFabcdef";
-static char    nch[]  = "\"\r\n\t";                          // forbidden in 
chains
+static char    nch[]  = "\r\n\t";                            // forbidden in 
chains
 
 
////////////////////////////////////////////////////////////////////////////////
 CBotToken*  CBotToken::NextToken(const char*& program, bool first)
@@ -278,14 +268,13 @@ CBotToken*  CBotToken::NextToken(const char*& program, 
bool first)
         // special case for strings
         if (token[0] == '\"' )
         {
-            while (c != 0 && !CharInList(c, nch))
+            while (c != 0 && c != '\"' && !CharInList(c, nch))
             {
                 if ( c == '\\' )
                 {
-                    c   = *(program++);                 // next character
-                    if ( c == 'n' ) c = '\n';
-                    if ( c == 'r' ) c = '\r';
-                    if ( c == 't' ) c = '\t';
+                    token += c;
+                    c = *(program++);
+                    if (c == 0 || CharInList(c, nch)) break;
                 }
                 token += c;
                 c = *(program++);
diff --git a/src/CBot/CBotUtils.cpp b/src/CBot/CBotUtils.cpp
index 4e28931..2bb4d8e 100644
--- a/src/CBot/CBotUtils.cpp
+++ b/src/CBot/CBotUtils.cpp
@@ -236,4 +236,49 @@ float GetNumFloat(const std::string& str)
     return static_cast<float>(num);
 }
 
+bool CharInList(const char c, const char* list)
+{
+    int i = 0;
+
+    while (list[i] != 0)
+    {
+        if (c == list[i++]) return true;
+    }
+
+    return false;
+}
+
+std::string CodePointToUTF8(unsigned int val)
+{
+    std::string s = "";
+
+    if (val < 0xD800 || (0xDFFF < val && val < 0x110000))
+    {
+        if (val < 0x80)
+        {
+            s.push_back(val);
+        }
+        else if (val < 0x800)
+        {
+            s.push_back(0xC0 + (val >> 6));
+            s.push_back(0x80 + (val & 0x3F));
+        }
+        else if (val < 0x10000)
+        {
+            s.push_back(0xE0 + (val >> 12));
+            s.push_back(0x80 + ((val >> 6) & 0x3F));
+            s.push_back(0x80 + (val & 0x3F));
+        }
+        else
+        {
+            s.push_back(0xF0 + (val >> 18));
+            s.push_back(0x80 + ((val >> 12) & 0x3F));
+            s.push_back(0x80 + ((val >> 6) & 0x3F));
+            s.push_back(0x80 + (val & 0x3F));
+        }
+    }
+
+    return s;
+}
+
 } // namespace CBot
diff --git a/src/CBot/CBotUtils.h b/src/CBot/CBotUtils.h
index 418e10b..6db107a 100644
--- a/src/CBot/CBotUtils.h
+++ b/src/CBot/CBotUtils.h
@@ -96,6 +96,21 @@ long GetNumInt(const std::string& str);
  */
 float GetNumFloat(const std::string& str);
 
+/*!
+ * \brief Search a null-terminated string for a char value.
+ * \param c The char to find.
+ * \param list The string to search.
+ * \return true if the char is found.
+ */
+bool CharInList(const char c, const char* list);
+
+/*!
+ * \brief Converts a Unicode code point to UTF-8 encoded character.
+ * \param val Code point value.
+ * \return UTF-8 encoded string or empty string.
+ */
+std::string CodePointToUTF8(unsigned int val);
+
 template<typename T> class CBotLinkedList
 {
 public:
diff --git a/src/common/restext.cpp b/src/common/restext.cpp
index 3d16603..ac526af 100644
--- a/src/common/restext.cpp
+++ b/src/common/restext.cpp
@@ -731,6 +731,12 @@ void InitializeRestext()
     stringsCbot[CBot::CBotErrNoClassName]   = TR("Class name expected");
     stringsCbot[CBot::CBotErrNoReturn]      = TR("Non-void function needs 
\"return;\"");
     stringsCbot[CBot::CBotErrDefaultValue]  = TR("This parameter needs a 
default value");
+    stringsCbot[CBot::CBotErrEndQuote]      = TR("Missing end quote");
+    stringsCbot[CBot::CBotErrBadEscape]     = TR("Unknown escape sequence");
+    stringsCbot[CBot::CBotErrOctalRange]    = TR("Octal value out of range");
+    stringsCbot[CBot::CBotErrHexDigits]     = TR("Missing hex digits after 
escape sequence");
+    stringsCbot[CBot::CBotErrHexRange]      = TR("Hex value out of range");
+    stringsCbot[CBot::CBotErrUnicodeName]   = TR("Invalid universal character 
name");
 
     stringsCbot[CBot::CBotErrZeroDiv]       = TR("Dividing by zero");
     stringsCbot[CBot::CBotErrNotInit]       = TR("Variable not initialized");
diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp
index 9e264e1..f94b72d 100644
--- a/test/unit/CBot/CBot_test.cpp
+++ b/test/unit/CBot/CBot_test.cpp
@@ -1533,6 +1533,120 @@ TEST_F(CBotUT, String)
         "    ASSERT(c == \"Colobot!\");\n"
         "}\n"
     );
+
+    ExecuteTest(
+        "extern void MissingEndQuote()\n"
+        "{\n"
+        "    \"Colobot...\n"
+        "}\n",
+        CBotErrEndQuote
+    );
+}
+
+TEST_F(CBotUT, StringEscapeCodes)
+{
+    ExecuteTest(
+        "extern void HexEscapeCodes()\n"
+        "{\n"
+        "    ASSERT(\"  \\x07  \" == \"  \\a  \");\n"
+        "    ASSERT(\"  \\x08  \" == \"  \\b  \");\n"
+        "    ASSERT(\"  \\x09  \" == \"  \\t  \");\n"
+        "    ASSERT(\"  \\x0A  \" == \"  \\n  \");\n"
+        "    ASSERT(\"  \\x0B  \" == \"  \\v  \");\n"
+        "    ASSERT(\"  \\x0C  \" == \"  \\f  \");\n"
+        "    ASSERT(\"  \\x0D  \" == \"  \\r  \");\n"
+        "    ASSERT(\"  \\x22  \" == \"  \\\"  \");\n"
+        "    ASSERT(\"  \\x27  \" == \"  \\\'  \");\n"
+        "    ASSERT(\"  \\x5C  \" == \"  \\\\  \");\n"
+        "    string test = \"\\x31 \\x32 \\x33\";\n"
+        "    ASSERT(test == \"1 2 3\");\n"
+        "}\n"
+        "extern void OctalEscapeCodes()\n"
+        "{\n"
+        "    ASSERT(\"  \\000  \" == \"  \\x00  \");\n"
+        "    ASSERT(\"  \\007  \" == \"  \\x07  \");\n"
+        "    ASSERT(\"  \\010  \" == \"  \\x08  \");\n"
+        "    ASSERT(\"  \\011  \" == \"  \\x09  \");\n"
+        "    ASSERT(\"  \\012  \" == \"  \\x0A  \");\n"
+        "    ASSERT(\"  \\013  \" == \"  \\x0B  \");\n"
+        "    ASSERT(\"  \\014  \" == \"  \\x0C  \");\n"
+        "    ASSERT(\"  \\015  \" == \"  \\x0D  \");\n"
+        "    ASSERT(\"  \\042  \" == \"  \\x22  \");\n"
+        "    ASSERT(\"  \\047  \" == \"  \\x27  \");\n"
+        "    ASSERT(\"  \\134  \" == \"  \\x5C  \");\n"
+        "    string test = \"\\101 \\102 \\103\";\n"
+        "    ASSERT(test == \"A B C\");\n"
+        "}\n"
+        "extern void UnicodeEscapeCodesToUTF_8()\n"
+        "{\n"
+        "    ASSERT(\"  \\u0000  \" == \"  \\0  \");\n"
+        "    ASSERT(\"  \\u0007  \" == \"  \\a  \");\n"
+        "    ASSERT(\"  \\u0008  \" == \"  \\b  \");\n"
+        "    ASSERT(\"  \\u0009  \" == \"  \\t  \");\n"
+        "    ASSERT(\"  \\u000A  \" == \"  \\n  \");\n"
+        "    ASSERT(\"  \\u000B  \" == \"  \\v  \");\n"
+        "    ASSERT(\"  \\u000C  \" == \"  \\f  \");\n"
+        "    ASSERT(\"  \\u000D  \" == \"  \\r  \");\n"
+        "    ASSERT(\"  \\u0022  \" == \"  \\\"  \");\n"
+        "    ASSERT(\"  \\u0027  \" == \"  \\\'  \");\n"
+        "    ASSERT(\"  \\u005C  \" == \"  \\\\  \");\n"
+        "\n"
+        "    ASSERT(\"\\u00A9\" == \"\\xC2\\xA9\");\n"
+        "    ASSERT(\"\\u00AE\" == \"\\xC2\\xAE\");\n"
+        "    ASSERT(\"\\u262E\" == \"\\xE2\\x98\\xAE\");\n"
+        "    ASSERT(\"\\u262F\" == \"\\xE2\\x98\\xAF\");\n"
+        "    ASSERT(\"\\U0001F60E\" == \"\\xF0\\x9F\\x98\\x8E\");\n"
+        "    ASSERT(\"\\U0001F61C\" == \"\\xF0\\x9F\\x98\\x9C\");\n"
+        "    ASSERT(\"\\U0001F6E0\" == \"\\xF0\\x9F\\x9B\\xA0\");\n"
+        "}\n"
+        "extern void UnicodeMaxCharacterNameToUTF_8()\n"
+        "{\n"
+        "    ASSERT(\"\\U0010FFFF\" == \"\\xF4\\x8F\\xBF\\xBF\");\n"
+        "}\n"
+    );
+}
+
+TEST_F(CBotUT, StringEscapeCodeErrors)
+{
+    ExecuteTest(
+        "extern void UnknownEscapeSequence()\n"
+        "{\n"
+        "    \"Unknown: \\p \";\n"
+        "}\n",
+        CBotErrBadEscape
+    );
+
+    ExecuteTest(
+        "extern void MissingHexDigits()\n"
+        "{\n"
+        "    \"  \\x  \";\n"
+        "}\n",
+        CBotErrHexDigits
+    );
+
+    ExecuteTest(
+        "extern void HexValueOutOfRange()\n"
+        "{\n"
+        "    \"  \\x100  \";\n"
+        "}\n",
+        CBotErrHexRange
+    );
+
+    ExecuteTest(
+        "extern void OctalValueOutOfRange()\n"
+        "{\n"
+        "    \"  \\400  \";\n"
+        "}\n",
+        CBotErrOctalRange
+    );
+
+    ExecuteTest(
+        "extern void BadUnicodeCharacterName()\n"
+        "{\n"
+        "    \"  \\U00110000  \";\n"
+        "}\n",
+        CBotErrUnicodeName
+    );
 }
 
 // TODO: not implemented, see issue #694

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-games/colobot.git

_______________________________________________
Pkg-games-commits mailing list
Pkg-games-commits@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

Reply via email to