From c177597d6da5dedb32aa176e8370db8ffb7f87aa Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Wed, 19 Apr 2017 21:25:04 +0200
Subject: Handled static strings as well as dynamic strings in comments.

---
 ChangeLog                                    |  32 +++
 plugins/pychrysa/analysis/db/items/comment.c |  19 +-
 plugins/readelf/header.c                     |   2 +-
 src/analysis/db/cdb.c                        |   4 +-
 src/analysis/db/client.c                     |   4 +-
 src/analysis/db/item.c                       |   2 +-
 src/analysis/db/items/bookmark.c             |   2 +-
 src/analysis/db/items/comment.c              | 300 +++++++++++++++++++++++----
 src/analysis/db/items/comment.h              |  10 +-
 src/analysis/db/misc/rlestr.c                | 107 +++++++++-
 src/analysis/db/misc/rlestr.h                |  25 ++-
 src/analysis/db/server.c                     |   2 +-
 src/common/array.c                           |   2 +-
 src/common/array.h                           |   2 +-
 src/format/symbol.h                          |  18 +-
 15 files changed, 461 insertions(+), 70 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 91ea5c2..448352b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+17-04-19  Cyrille Bagard <nocbos@gmail.com>
+
+	* plugins/pychrysa/analysis/db/items/comment.c:
+	Update code.
+
+	* plugins/readelf/header.c:
+	Give the new macro for creating comments a try.
+
+	* src/analysis/db/cdb.c:
+	* src/analysis/db/client.c:
+	* src/analysis/db/item.c:
+	* src/analysis/db/items/bookmark.c:
+	Update code.
+
+	* src/analysis/db/items/comment.c:
+	* src/analysis/db/items/comment.h:
+	Handle static strings as well as dynamic strings in comments.
+
+	* src/analysis/db/misc/rlestr.c:
+	* src/analysis/db/misc/rlestr.h:
+	Handle static strings as well as dynamic strings.
+
+	* src/analysis/db/server.c:
+	Update code.
+
+	* src/common/array.c:
+	* src/common/array.h:
+	Mark the added item as constant before the copy.
+
+	* src/format/symbol.h:
+	Update code.
+
 17-04-15  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/arch/immediate.c:
diff --git a/plugins/pychrysa/analysis/db/items/comment.c b/plugins/pychrysa/analysis/db/items/comment.c
index 4a90f09..1062cc9 100644
--- a/plugins/pychrysa/analysis/db/items/comment.c
+++ b/plugins/pychrysa/analysis/db/items/comment.c
@@ -25,6 +25,7 @@
 #include "comment.h"
 
 
+#include <malloc.h>
 #include <pygobject.h>
 
 
@@ -108,13 +109,25 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject
 
 static PyObject *py_db_comment_get_text(PyObject *self, void *closure)
 {
+    PyObject *result;                       /* Résultat à retourner        */
     GDbComment *comment;                    /* Commentaire à consulter     */
-    const char *content;                    /* Contenu textuel associé     */
+    char *text;                             /* Contenu textuel associé     */
 
     comment = G_DB_COMMENT(pygobject_get(self));
-    content = g_db_comment_get_text(comment);
+    text = g_db_comment_get_text(comment);
 
-    return PyUnicode_FromString(content);
+    if (text == NULL)
+    {
+        result = Py_None;
+        Py_INCREF(result);
+    }
+    else
+    {
+        result = PyUnicode_FromString(text);
+        free(text);
+    }
+
+    return result;
 
 }
 
diff --git a/plugins/readelf/header.c b/plugins/readelf/header.c
index 75e30fe..d0aee92 100644
--- a/plugins/readelf/header.c
+++ b/plugins/readelf/header.c
@@ -70,7 +70,7 @@ bool annotate_elf_header(GElfFormat *format)
     SET_IMM_DISPLAY(instr, operand, 2, IOD_CHAR);
     SET_IMM_DISPLAY(instr, operand, 3, IOD_CHAR);
 
-    ADD_RAW_AS_SYM(format, symbol, instr, comment, _("ELF magic number"));
+    ADD_RAW_AS_SYM_CST(format, symbol, instr, comment, _("ELF magic number"));
 
     /* EI_CLASS (4) */
 
diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index 49662e8..78f2aa8 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -287,7 +287,7 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const rle_string *hash, cons
 
     result = g_object_new(G_TYPE_CDB_ARCHIVE, NULL);
 
-    dup_rle_string(&result->hash, hash);
+    dup_into_rle_string(&result->hash, get_rle_string(hash));
 
     /* Chemin de l'archive */
 
@@ -1061,7 +1061,7 @@ DBError g_cdb_archive_add_client(GCdbArchive *archive, int fd, const rle_string
     archive->clients = (cdb_client *)realloc(archive->clients, ++archive->count * sizeof(cdb_client));
 
     archive->clients[archive->count - 1].fd = fd;
-    dup_rle_string(&archive->clients[archive->count - 1].user, user);
+    dup_into_rle_string(&archive->clients[archive->count - 1].user, get_rle_string(user));
 
     /* Démarrage ou redémarrage du processus d'écoute */
 
diff --git a/src/analysis/db/client.c b/src/analysis/db/client.c
index 309d9ed..769eab7 100644
--- a/src/analysis/db/client.c
+++ b/src/analysis/db/client.c
@@ -187,7 +187,7 @@ GDbClient *g_db_client_new(char *author, char *kfile, const char *name, const ch
 
     result->name = name;
 
-    set_rle_string(&result->hash, hash);
+    init_static_rle_string(&result->hash, hash);
     result->collections = collections;
 
     return result;
@@ -386,7 +386,7 @@ static bool g_db_client_start_common(GDbClient *client, const char *desc)
     status = pack_rle_string(&client->hash, &out_pbuf);
     if (!status) goto gdcs_error;
 
-    init_rle_string(&user, client->author);
+    dup_into_rle_string(&user, client->author); /* FIXME : src ? */
 
     status = pack_rle_string(&user, &out_pbuf);
     if (!status) goto gdcs_error;
diff --git a/src/analysis/db/item.c b/src/analysis/db/item.c
index 20276d6..d2c1652 100644
--- a/src/analysis/db/item.c
+++ b/src/analysis/db/item.c
@@ -122,7 +122,7 @@ static void g_db_item_init(GDbItem *item)
     status = g_generic_config_get_value(get_main_configuration(), MPK_AUTHOR_NAME, &author);
     assert(status);
 
-    set_rle_string(&item->author, author);
+    set_static_rle_string(&item->author, author);
 
     item->is_volatile = false;
 
diff --git a/src/analysis/db/items/bookmark.c b/src/analysis/db/items/bookmark.c
index 9d3b691..0db847b 100644
--- a/src/analysis/db/items/bookmark.c
+++ b/src/analysis/db/items/bookmark.c
@@ -604,7 +604,7 @@ const char *g_db_bookmark_get_comment(const GDbBookmark *bookmark)
 
 void g_db_bookmark_set_comment(GDbBookmark *bookmark, const char *comment)
 {
-    set_rle_string(&bookmark->comment, comment);
+    dup_into_rle_string(&bookmark->comment, comment);
 
 }
 
diff --git a/src/analysis/db/items/comment.c b/src/analysis/db/items/comment.c
index b43c1e6..beec629 100644
--- a/src/analysis/db/items/comment.c
+++ b/src/analysis/db/items/comment.c
@@ -36,6 +36,7 @@
 #include "../collection-int.h"
 #include "../item-int.h"
 #include "../../human/asm/lang.h"
+#include "../../../common/array.h"
 #include "../../../common/extstr.h"
 #include "../../../glibext/linegen-int.h"
 
@@ -52,10 +53,8 @@ struct _GDbComment
     vmpa2t addr;                            /* Adresse du commentaire      */
     BufferLineFlags flags;                  /* Identification de l'accroche*/
 
-    rle_string text;                        /* Contenu du commentaire      */
-
-    char **lines;                           /* Lignes brutes à représenter */
-    size_t count;                           /* Quantité de ces lignes      */
+    flat_array_t *text;                     /* Contenu du commentaire      */
+    size_t count;                           /* Quantité de lignes affichées*/
 
     bool inlined;                           /* Intégration dans une ligne ?*/
 
@@ -99,7 +98,7 @@ static gint g_db_comment_cmp(GDbComment *, GDbComment *, bool);
 static bool g_db_comment_unpack(GDbComment *, packed_buffer *);
 
 /* Exporte la définition d'un commentaire dans un flux réseau. */
-static bool g_db_comment_pack(const GDbComment *, packed_buffer *);
+static bool g_db_comment_pack(GDbComment *, packed_buffer *);
 
 /* Construit la description humaine d'un commentaire. */
 static void g_db_comment_build_label(GDbComment *);
@@ -114,19 +113,22 @@ static bool g_db_comment_apply(GDbComment *, GLoadedBinary *);
 static bool g_db_comment_cancel(GDbComment *, GLoadedBinary *);
 
 /* Constitue les champs destinés à une insertion / modification. */
-static bool g_db_comment_prepare_db_statement(const GDbComment *, bound_value **, size_t *);
+static bool g_db_comment_prepare_db_statement(GDbComment *, bound_value **, size_t *);
 
 /* Charge les valeurs utiles pour un commentaire. */
 static bool g_db_comment_load(GDbComment *, const bound_value *, size_t);
 
-/* Définit le commentaire associé à un commentaire. */
-static void g_db_comment_set_text(GDbComment *, const char *);
+/* Associe un contenu formaté supplémentaire à un commentaire. */
+static void g_db_comment_add_rle_string(GDbComment *, const rle_string *);
 
 
 
 /* ------------------------ OFFRE DE CAPACITES DE GENERATION ------------------------ */
 
 
+/* Calcule le nombre de lignes suite à un changement de contenu. */
+static void g_db_comment_update_count_lines(GDbComment *);
+
 /* Indique le nombre de ligne prêtes à être générées. */
 static size_t g_db_comment_count_lines(const GDbComment *);
 
@@ -253,7 +255,7 @@ static void g_db_comment_class_init(GDbCommentClass *klass)
 
 static void g_db_comment_init(GDbComment *comment)
 {
-    comment->lines = NULL;
+    comment->text = NULL;
     comment->count = 0;
 
 }
@@ -298,12 +300,6 @@ static void g_db_comment_dispose(GDbComment *comment)
 {
     size_t i;                               /* Boucle de parcours          */
 
-    for (i = 0; i < comment->count; i++)
-        free(comment->lines[i]);
-
-    if (comment->lines != NULL)
-        free(comment->lines);
-
     for (i = 0; i < comment->old_count; i++)
         g_object_unref(G_OBJECT(comment->old_inlined[i]));
 
@@ -329,7 +325,25 @@ static void g_db_comment_dispose(GDbComment *comment)
 
 static void g_db_comment_finalize(GDbComment *comment)
 {
-    exit_rle_string(&comment->text);
+    size_t count;                           /* Nombre d'éléments textuels  */
+    size_t i;                               /* Boucle de parcours          */
+    rle_string *string;                     /* Chaîne à traiter            */
+
+    lock_flat_array(&comment->text);
+
+    count = count_flat_array_items(comment->text);
+
+    for (i = 0; i < count; i++)
+    {
+        string = get_flat_array_item(comment->text, 0, sizeof(rle_string));
+
+        exit_rle_string(string);
+
+        rem_item_from_flat_array(&comment->text, 0, sizeof(rle_string));
+
+    }
+
+    unlock_flat_array(&comment->text);
 
     G_OBJECT_CLASS(g_db_comment_parent_class)->finalize(G_OBJECT(comment));
 
@@ -340,7 +354,6 @@ static void g_db_comment_finalize(GDbComment *comment)
 *                                                                             *
 *  Paramètres  : addr       = adresse inamovible localisant une position.     *
 *                flags      = indentifiants supplémentaires de ligne visée.   *
-*                text       = commentaire construit ou NULL.                  *
 *                repeatable = repétition aux instructions liées ?             *
 *                                                                             *
 *  Description : Crée une définition de commentaire dans une zone de texte.   *
@@ -351,7 +364,7 @@ static void g_db_comment_finalize(GDbComment *comment)
 *                                                                             *
 ******************************************************************************/
 
-GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags, const char *text, bool repeatable)
+GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags, bool repeatable)
 {
     GDbComment *result;                    /* Instance à retourner        */
 
@@ -361,8 +374,6 @@ GDbComment *g_db_comment_new_inlined(const vmpa2t *addr, BufferLineFlags flags,
 
     result->flags = flags;
 
-    g_db_comment_set_text(result, text);
-
     result->inlined = true;
 
     result->repeatable = repeatable;
@@ -397,7 +408,7 @@ GDbComment *g_db_comment_new_area(const vmpa2t *addr, BufferLineFlags flags, con
 
     result->flags = flags;
 
-    g_db_comment_set_text(result, text);
+    g_db_comment_add_dynamic_text(result, strdup(text));
 
     result->inlined = false;
 
@@ -425,11 +436,32 @@ GDbComment *g_db_comment_new_area(const vmpa2t *addr, BufferLineFlags flags, con
 static gint g_db_comment_cmp(GDbComment *a, GDbComment *b, bool with)
 {
     gint result;                            /* Bilan de la comparaison     */
+    char *string_a;                         /* Texte du commentaire A      */
+    char *string_b;                         /* Texte du commentaire B      */
 
     result = cmp_vmpa_by_phy(&a->addr, &b->addr);
 
     if (result == 0)
-        result = cmp_rle_string(&a->text, &b->text);
+    {
+        string_a = g_db_comment_get_text(a);
+        string_b = g_db_comment_get_text(b);
+
+        if (string_a == NULL && string_b == NULL)
+            result = 0;
+
+        else if (string_a != NULL && string_b == NULL)
+            result = 1;
+
+        else if (string_a == NULL && string_b != NULL)
+            result = -1;
+
+        else
+            result = strcmp(string_a, string_b);
+
+        if (string_a != NULL) free(string_a);
+        if (string_b != NULL) free(string_b);
+
+    }
 
     if (result == 0)
         result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->cmp(G_DB_ITEM(a), G_DB_ITEM(b), with);
@@ -456,6 +488,7 @@ static bool g_db_comment_unpack(GDbComment *comment, packed_buffer *pbuf)
 {
     bool result;                            /* Bilan à retourner           */
     uint32_t tmp32;                         /* Valeur sur 32 bits          */
+    rle_string string;                      /* Texte brut récupéré         */
     uint8_t tmp8;                           /* Valeur sur 8 bits           */
 
     result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->unpack(G_DB_ITEM(comment), pbuf);
@@ -470,7 +503,13 @@ static bool g_db_comment_unpack(GDbComment *comment, packed_buffer *pbuf)
     }
 
     if (result)
-        result = unpack_rle_string(&comment->text, pbuf);
+    {
+        result = unpack_rle_string(&string, pbuf);
+
+        if (!is_rle_string_empty(&string) > 0)
+            g_db_comment_add_rle_string(comment, &string);
+
+    }
 
     if (result)
     {
@@ -502,9 +541,10 @@ static bool g_db_comment_unpack(GDbComment *comment, packed_buffer *pbuf)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_db_comment_pack(const GDbComment *comment, packed_buffer *pbuf)
+static bool g_db_comment_pack(GDbComment *comment, packed_buffer *pbuf)
 {
     bool result;                            /* Bilan à retourner           */
+    rle_string text;                        /* Texte brut récupéré         */
 
     result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->pack(G_DB_ITEM(comment), pbuf);
 
@@ -515,7 +555,11 @@ static bool g_db_comment_pack(const GDbComment *comment, packed_buffer *pbuf)
         result = extend_packed_buffer(pbuf, (uint32_t []) { comment->flags }, sizeof(uint32_t), true);
 
     if (result)
-        result = pack_rle_string(&comment->text, pbuf);
+    {
+        init_dynamic_rle_string(&text, g_db_comment_get_text(comment));
+        result = pack_rle_string(&text, pbuf);
+        exit_rle_string(&text);
+    }
 
     if (result)
         result = extend_packed_buffer(pbuf, (uint8_t []) { comment->inlined }, sizeof(uint8_t), true);
@@ -543,10 +587,15 @@ static bool g_db_comment_pack(const GDbComment *comment, packed_buffer *pbuf)
 static void g_db_comment_build_label(GDbComment *comment)
 {
     VMPA_BUFFER(loc);                       /* Indication de position      */
+    size_t count;                           /* Nombre d'éléments textuels  */
 
     vmpa2_to_string(&comment->addr, MDS_UNDEFINED, loc, NULL);
 
-    if (is_rle_string_empty(&comment->text))
+    lock_flat_array(&comment->text);
+    count = count_flat_array_items(comment->text);
+    unlock_flat_array(&comment->text);
+
+    if (count == 0)
         asprintf(&G_DB_ITEM(comment)->label, _("Delete comment at %s"), loc);
 
     else
@@ -917,10 +966,11 @@ static bool g_db_comment_cancel(GDbComment *comment, GLoadedBinary *binary)
 *                                                                             *
 ******************************************************************************/
 
-static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_value **values, size_t *count)
+static bool g_db_comment_prepare_db_statement(GDbComment *comment, bound_value **values, size_t *count)
 {
     bool status;                            /* Bilan d'opération initiale  */
     bound_value *value;                     /* Valeur à éditer / définir   */
+    rle_string text;                        /* Texte brut récupéré         */
 
     status = G_DB_ITEM_CLASS(g_db_comment_parent_class)->prepare_stmt(G_DB_ITEM(comment), values, count);
     if (!status) return false;
@@ -939,7 +989,10 @@ static bool g_db_comment_prepare_db_statement(const GDbComment *comment, bound_v
     value->integer = comment->flags;
     value->delete = NULL;
 
-    status &= prepare_db_statement_for_rle_string(&comment->text, "text", values, count);
+    init_dynamic_rle_string(&text, g_db_comment_get_text(comment));
+    status &= prepare_db_statement_for_rle_string(&text, "text", values, count);
+    exit_rle_string(&text);
+
     if (!status) return false;
 
     *count += 2;
@@ -984,6 +1037,7 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si
 {
     bool result;                            /* Bilan à faire remonter      */
     const bound_value *value;               /* Valeur à éditer / définir   */
+    rle_string string;                      /* Texte brut récupéré         */
 
     result = G_DB_ITEM_CLASS(g_db_comment_parent_class)->load(G_DB_ITEM(comment), values, count);
 
@@ -999,7 +1053,10 @@ static bool g_db_comment_load(GDbComment *comment, const bound_value *values, si
 
     }
 
-    result &= load_rle_string(&comment->text, "text", values, count);
+    result &= load_rle_string(&string, "text", values, count);
+
+    if (result)
+        g_db_comment_add_rle_string(comment, &string);
 
     if (result)
     {
@@ -1051,15 +1108,38 @@ const vmpa2t *g_db_comment_get_address(GDbComment *comment)
 *                                                                             *
 *  Description : Fournit le commentaire associé à un commentaire.             *
 *                                                                             *
-*  Retour      : Commentaire existant ou NULL.                                *
+*  Retour      : Commentaire existant à libérer après usage ou NULL.          *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_db_comment_get_text(const GDbComment *comment)
+char *g_db_comment_get_text(GDbComment *comment)
 {
-    return get_rle_string(&comment->text);
+    char *result;                           /* Chaîne constituée à renvoyer*/
+    size_t count;                           /* Nombre d'éléments textuels  */
+    size_t i;                               /* Boucle de parcours          */
+    rle_string *string;                     /* Chaîne à consulter          */
+
+    result = NULL;
+
+    lock_flat_array(&comment->text);
+
+    count = count_flat_array_items(comment->text);
+
+    for (i = 0; i < count; i++)
+    {
+        string = get_flat_array_item(comment->text, 0, sizeof(rle_string));
+
+        assert(!is_rle_string_empty(string));
+
+        result = stradd(result, get_rle_string(string));
+
+    }
+
+    unlock_flat_array(&comment->text);
+
+    return result;
 
 }
 
@@ -1069,7 +1149,7 @@ const char *g_db_comment_get_text(const GDbComment *comment)
 *  Paramètres  : comment = informations à consulter.                          *
 *                text    = commentaire construit ou NULL.                     *
 *                                                                             *
-*  Description : Définit le commentaire associé à un commentaire.             *
+*  Description : Associe un contenu supplémentaire à un commentaire.          *
 *                                                                             *
 *  Retour      : -                                                            *
 *                                                                             *
@@ -1077,19 +1157,81 @@ const char *g_db_comment_get_text(const GDbComment *comment)
 *                                                                             *
 ******************************************************************************/
 
-static void g_db_comment_set_text(GDbComment *comment, const char *text)
+void g_db_comment_add_dynamic_text(GDbComment *comment, char *text)
 {
-    GCodingLanguage *lang;                  /* Langage de sortie préféré   */
+    rle_string string;                      /* Fragment de texte à ajouter */
+
+    if (text != NULL)
+    {
+        init_dynamic_rle_string(&string, text);
+
+        g_db_comment_add_rle_string(comment, &string);
 
-    set_rle_string(&comment->text, text);
+    }
+
+    else
+        g_db_comment_update_count_lines(comment);
+
+}
 
-    lang = g_asm_language_new();
 
-    comment->lines = strtoka(text, "\n", &comment->count);
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : comment = informations à consulter.                          *
+*                text    = commentaire construit ou NULL.                     *
+*                                                                             *
+*  Description : Associe un contenu statique supplémentaire à un commentaire. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
-    g_coding_language_encapsulate_comments(lang, &comment->lines, &comment->count);
+void g_db_comment_add_static_text(GDbComment *comment, const char *text)
+{
+    rle_string string;                      /* Fragment de texte à ajouter */
 
-    g_object_unref(G_OBJECT(lang));
+    if (text != NULL)
+    {
+        init_static_rle_string(&string, text);
+
+        g_db_comment_add_rle_string(comment, &string);
+
+    }
+
+    else
+        g_db_comment_update_count_lines(comment);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : comment = informations à consulter.                          *
+*                string  = commentaire établi à inétgrer.                     *
+*                                                                             *
+*  Description : Associe un contenu formaté supplémentaire à un commentaire.  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_comment_add_rle_string(GDbComment *comment, const rle_string *string)
+{
+    /* Extension du contenu */
+
+    lock_flat_array(&comment->text);
+
+    add_item_to_flat_array(&comment->text, string, sizeof(rle_string));
+
+    unlock_flat_array(&comment->text);
+
+    /* Mise à jour de la taille de rendu */
+
+    g_db_comment_update_count_lines(comment);
 
 }
 
@@ -1102,6 +1244,51 @@ static void g_db_comment_set_text(GDbComment *comment, const char *text)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : comment = informations à réactualiser.                       *
+*                                                                             *
+*  Description : Calcule le nombre de lignes suite à un changement de contenu.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_db_comment_update_count_lines(GDbComment *comment)
+{
+    char *full;                             /* Contenu textuel complet     */
+    char **lines;                           /* Lignes brutes à représenter */
+    GCodingLanguage *lang;                  /* Langage de sortie préféré   */
+    size_t i;                               /* Boucle de parcours          */
+
+    full = g_db_comment_get_text(comment);
+
+    if (full == NULL)
+        comment->count = 0;
+
+    else
+    {
+        lines = strtoka(full, "\n", &comment->count);
+
+        lang = g_asm_language_new();
+        g_coding_language_encapsulate_comments(lang, &lines, &comment->count);
+        g_object_unref(G_OBJECT(lang));
+
+        for (i = 0; i < comment->count; i++)
+            free(lines[i]);
+
+        if (lines != NULL)
+            free(lines);
+
+        free(full);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : comment = générateur à consulter.                            *
 *                                                                             *
 *  Description : Indique le nombre de ligne prêtes à être générées.           *
@@ -1206,7 +1393,38 @@ static BufferLineFlags g_db_comment_get_flags(const GDbComment *comment, size_t
 
 static void g_db_comment_print(GDbComment *comment, GBufferLine *line, size_t index, size_t repeat)
 {
-    g_buffer_line_append_text(line, BLC_COMMENTS, SL(comment->lines[repeat]), RTT_COMMENT, NULL);
+    char *full;                             /* Contenu textuel complet     */
+    size_t count;                           /* Quantité de ces lignes      */
+    char **lines;                           /* Lignes brutes à représenter */
+    GCodingLanguage *lang;                  /* Langage de sortie préféré   */
+    size_t i;                               /* Boucle de parcours          */
+
+    full = g_db_comment_get_text(comment);
+
+    if (full != NULL)
+    {
+        lines = strtoka(full, "\n", &count);
+
+        lang = g_asm_language_new();
+        g_coding_language_encapsulate_comments(lang, &lines, &count);
+        g_object_unref(G_OBJECT(lang));
+
+        if (count != comment->count)
+            printf("full=%s\n", full);
+
+        assert(count == comment->count);
+
+        g_buffer_line_append_text(line, BLC_COMMENTS, SL(lines[repeat]), RTT_COMMENT, NULL);
+
+        for (i = 0; i < count; i++)
+            free(lines[i]);
+
+        if (lines != NULL)
+            free(lines);
+
+        free(full);
+
+    }
 
 }
 
diff --git a/src/analysis/db/items/comment.h b/src/analysis/db/items/comment.h
index 03d1bff..ee68491 100644
--- a/src/analysis/db/items/comment.h
+++ b/src/analysis/db/items/comment.h
@@ -58,7 +58,7 @@ typedef struct _GDbCommentClass GDbCommentClass;
 GType g_db_comment_get_type(void);
 
 /* Crée une définition de commentaire dans une zone de texte. */
-GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, const char *, bool);
+GDbComment *g_db_comment_new_inlined(const vmpa2t *, BufferLineFlags, bool);
 
 /* Crée une définition de commentaire dans une zone de texte. */
 GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *, bool);
@@ -67,7 +67,13 @@ GDbComment *g_db_comment_new_area(const vmpa2t *, BufferLineFlags, const char *,
 const vmpa2t *g_db_comment_get_address(GDbComment *);
 
 /* Fournit le commentaire associé à un commentaire. */
-const char *g_db_comment_get_text(const GDbComment *);
+char *g_db_comment_get_text(GDbComment *);
+
+/* Associe un contenu supplémentaire à un commentaire. */
+void g_db_comment_add_dynamic_text(GDbComment *, char *);
+
+/*  Associe un contenu statique supplémentaire à un commentaire. */
+void g_db_comment_add_static_text(GDbComment *, const char *);
 
 
 
diff --git a/src/analysis/db/misc/rlestr.c b/src/analysis/db/misc/rlestr.c
index 39e2d99..c1d2d95 100644
--- a/src/analysis/db/misc/rlestr.c
+++ b/src/analysis/db/misc/rlestr.c
@@ -43,12 +43,73 @@
 *                                                                             *
 ******************************************************************************/
 
-void init_rle_string(rle_string *str, const char *data)
+void init_dynamic_rle_string(rle_string *str, char *data)
+{
+    if (data != NULL)
+    {
+        str->data = data;
+        str->length = strlen(data);
+        str->dynamic = true;
+    }
+    else
+    {
+        str->data = NULL;
+        str->length = 0;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : str  = représentation de chaîne à traiter.                   *
+*                data = données à conserver en mémoire.                       *
+*                                                                             *
+*  Description : Définit une représentation de chaîne de caractères constante.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void init_static_rle_string(rle_string *str, const char *data)
+{
+    if (data != NULL)
+    {
+        str->cst_data = data;
+        str->length = strlen(data);
+        str->dynamic = false;
+    }
+    else
+    {
+        str->data = NULL;
+        str->length = 0;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : str  = représentation de chaîne à traiter.                   *
+*                data = données à conserver en mémoire.                       *
+*                                                                             *
+*  Description : Copie une chaîne de caractères existante.                    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void dup_into_rle_string(rle_string *str, const char *data)
 {
     if (data != NULL)
     {
         str->data = strdup(data);
         str->length = strlen(data);
+        str->dynamic = true;
     }
     else
     {
@@ -72,15 +133,44 @@ void init_rle_string(rle_string *str, const char *data)
 *                                                                             *
 ******************************************************************************/
 
-void set_rle_string(rle_string *str, const char *data)
+void set_dynamic_rle_string(rle_string *str, char *data)
 {
     if (str->data != NULL)
         unset_rle_string(str);
 
     if (data != NULL)
     {
-        str->data = strdup(data);
+        str->data = data;
+        str->length = strlen(data);
+        str->dynamic = true;
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : str  = représentation de chaîne à traiter.                   *
+*                data = données à conserver en mémoire.                       *
+*                                                                             *
+*  Description : Constitue une représentation de chaîne de caractères stable. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_static_rle_string(rle_string *str, const char *data)
+{
+    if (str->data != NULL)
+        unset_rle_string(str);
+
+    if (data != NULL)
+    {
+        str->cst_data = data;
         str->length = strlen(data);
+        str->dynamic = false;
     }
 
 }
@@ -102,9 +192,10 @@ void unset_rle_string(rle_string *str)
 {
     if (str->data != NULL)
     {
-        free(str->data);
-        str->data = NULL;
+        if (str->dynamic)
+            free(str->data);
 
+        str->data = NULL;
         str->length = 0;
 
     }
@@ -184,6 +275,7 @@ bool unpack_rle_string(rle_string *str, packed_buffer *pbuf)
     if (result && str->length > 0)
     {
         str->data = (char *)malloc(str->length + 1);
+        str->dynamic = true;
 
         result = extract_packed_buffer(pbuf, str->data, str->length + 1, false);
 
@@ -323,11 +415,12 @@ bool load_rle_string(rle_string *str, const char *name, const bound_value *value
     switch (value->type)
     {
         case SQLITE_TEXT:
-            set_rle_string(str, value->cstring);
+            unset_rle_string(str);
+            dup_into_rle_string(str, value->cstring);
             break;
 
         case SQLITE_NULL:
-            set_rle_string(str, NULL);
+            unset_rle_string(str);
             break;
 
         default:
diff --git a/src/analysis/db/misc/rlestr.h b/src/analysis/db/misc/rlestr.h
index be76f17..82a7d8c 100644
--- a/src/analysis/db/misc/rlestr.h
+++ b/src/analysis/db/misc/rlestr.h
@@ -38,18 +38,28 @@
 /* Informations de base pour tout élément ajouté */
 typedef struct _rle_string
 {
-    char *data;                             /* Chaîne de caractères        */
-    uint32_t length;                        /* Taille de la chaîne         */
+    union
+    {
+        char *data;                         /* Chaîne de caractères        */
+        const char *cst_data;               /* Autre version de chaîne     */
+    };
+
+    uint16_t length;                        /* Taille de la chaîne         */
+    bool dynamic;                           /* Type d'allocation utilisée  */
 
 } rle_string;
 
 
 /* Définit une représentation de chaîne de caractères. */
-void init_rle_string(rle_string *, const char *);
+void init_dynamic_rle_string(rle_string *, char *);
+
+/* Définit une représentation de chaîne de caractères constante. */
+void init_static_rle_string(rle_string *, const char *);
 
-#define exit_rle_string(rle) /* TODO */
+/* Copie une chaîne de caractères existante. */
+void dup_into_rle_string(rle_string *, const char *);
 
-#define dup_rle_string(dst, src) init_rle_string(dst, (src)->data);
+#define exit_rle_string(rle) unset_rle_string(rle)
 
 #define get_rle_string(rle) (rle)->data
 
@@ -58,7 +68,10 @@ void init_rle_string(rle_string *, const char *);
 #define is_rle_string_empty(rle) ((rle)->data == NULL)
 
 /* Constitue une représentation de chaîne de caractères. */
-void set_rle_string(rle_string *, const char *);
+void set_dynamic_rle_string(rle_string *, char *);
+
+/* Constitue une représentation de chaîne de caractères stable. */
+void set_static_rle_string(rle_string *, const char *);
 
 /* Libère la mémoire associée à la représentation. */
 void unset_rle_string(rle_string *);
diff --git a/src/analysis/db/server.c b/src/analysis/db/server.c
index 748af4e..0270201 100644
--- a/src/analysis/db/server.c
+++ b/src/analysis/db/server.c
@@ -394,7 +394,7 @@ static bool g_db_server_register_user(GDbServer *server, const char *author, cha
     server->users = (registered_user *)realloc(server->users,
                                                ++server->users_count * sizeof(registered_user));
 
-    init_rle_string(&server->users[server->users_count - 1].author, author);
+    dup_into_rle_string(&server->users[server->users_count - 1].author, author);    /* FIXME : src ? */
     server->users[server->users_count - 1].key_file = kfile;
 
     return true;
diff --git a/src/common/array.c b/src/common/array.c
index a4b55f4..641a885 100644
--- a/src/common/array.c
+++ b/src/common/array.c
@@ -206,7 +206,7 @@ size_t count_flat_array_items(const flat_array_t *array)
 *                                                                             *
 ******************************************************************************/
 
-void add_item_to_flat_array(flat_array_t **array, void *item, size_t size)
+void add_item_to_flat_array(flat_array_t **array, const void *item, size_t size)
 {
     ext_flat_array_t *extended;             /* Version de tableau étendue  */
 
diff --git a/src/common/array.h b/src/common/array.h
index 33558ee..416800d 100644
--- a/src/common/array.h
+++ b/src/common/array.h
@@ -43,7 +43,7 @@ void unlock_flat_array(flat_array_t **);
 size_t count_flat_array_items(const flat_array_t *);
 
 /* Ajoute un élément supplémentaire à un tableau. */
-void add_item_to_flat_array(flat_array_t **, void *, size_t);
+void add_item_to_flat_array(flat_array_t **, const void *, size_t);
 
 /* Remplace un élément d'un tableau compressé par un autre. */
 void rpl_item_in_flat_array(flat_array_t *, size_t, void *, size_t);
diff --git a/src/format/symbol.h b/src/format/symbol.h
index 2b8abf8..7389195 100644
--- a/src/format/symbol.h
+++ b/src/format/symbol.h
@@ -147,7 +147,23 @@ GDbComment *g_binary_symbol_get_comment(const GBinSymbol *);
         bool __result;                                                      \
         const vmpa2t *__addr;                                               \
         __addr = get_mrange_addr(g_arch_instruction_get_range(_ins));       \
-        _cmt = g_db_comment_new_inlined(__addr, BLF_HAS_CODE, _txt, false); \
+        _cmt = g_db_comment_new_inlined(__addr, BLF_HAS_CODE, false);       \
+        g_db_comment_add_static_text(_cmt, strdup(_txt)); /* ! */           \
+        g_db_item_set_volatile(G_DB_ITEM(_cmt), true);                      \
+        _sym = g_binary_symbol_new(STP_DATA);                               \
+        g_binary_symbol_attach_instruction(_sym, _ins);                     \
+        g_binary_symbol_set_comment(_sym, _cmt);                            \
+        __result = g_binary_format_add_symbol(G_BIN_FORMAT(_fmt), _sym);    \
+        __result;                                                           \
+    })
+
+#define ADD_RAW_AS_SYM_CST(_fmt, _sym, _ins, _cmt, _txt)                    \
+    ({                                                                      \
+        bool __result;                                                      \
+        const vmpa2t *__addr;                                               \
+        __addr = get_mrange_addr(g_arch_instruction_get_range(_ins));       \
+        _cmt = g_db_comment_new_inlined(__addr, BLF_HAS_CODE, false);       \
+        g_db_comment_add_static_text(_cmt, _txt);                           \
         g_db_item_set_volatile(G_DB_ITEM(_cmt), true);                      \
         _sym = g_binary_symbol_new(STP_DATA);                               \
         g_binary_symbol_attach_instruction(_sym, _ins);                     \
-- 
cgit v0.11.2-87-g4458