From 792b330c1bbe573a591687d25e14d4cd1eccd3c6 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 30 Jan 2016 18:23:16 +0100
Subject: Introduced a format switch to distinguish different kinds of
 definitions.

---
 ChangeLog                          |  35 ++++++
 configure.ac                       |   1 +
 src/arch/arm/v7/opdefs/Makefile.am |  37 +++---
 tools/d2c/Makefile.am              |   3 +-
 tools/d2c/bits/manager.c           |  14 +--
 tools/d2c/coder.c                  | 248 ++++++++++++++++++++++++++++++++++---
 tools/d2c/coder.h                  |  18 ++-
 tools/d2c/d2c.mk                   |  37 ++++--
 tools/d2c/d2c_genmakefile.sh       |  60 ++++++---
 tools/d2c/format/Makefile.am       |  31 +++++
 tools/d2c/format/decl.h            |  37 ++++++
 tools/d2c/format/grammar.y         | 107 ++++++++++++++++
 tools/d2c/format/manager.c         | 145 ++++++++++++++++++++++
 tools/d2c/format/manager.h         |  50 ++++++++
 tools/d2c/format/tokens.l          |  26 ++++
 tools/d2c/grammar.y                |  79 +++++++++---
 tools/d2c/pproc.c                  |  26 ++++
 tools/d2c/pproc.h                  |   3 +
 tools/d2c/spec.c                   | 134 +++++++++++++++++++-
 tools/d2c/spec.h                   |   7 ++
 tools/d2c/tokens.l                 | 110 ++++++----------
 21 files changed, 1055 insertions(+), 153 deletions(-)
 create mode 100644 tools/d2c/format/Makefile.am
 create mode 100644 tools/d2c/format/decl.h
 create mode 100644 tools/d2c/format/grammar.y
 create mode 100644 tools/d2c/format/manager.c
 create mode 100644 tools/d2c/format/manager.h
 create mode 100644 tools/d2c/format/tokens.l

diff --git a/ChangeLog b/ChangeLog
index b50d117..8d049fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,40 @@
 16-01-30  Cyrille Bagard <nocbos@gmail.com>
 
+	* configure.ac:
+	Add the new Makefile from the 'tools/d2c/format' directory.
+
+	* src/arch/arm/v7/opdefs/Makefile.am:
+	Update the Makefile definition.
+
+	* tools/d2c/Makefile.am:
+	Add the 'format/libd2cformat.la' archive into d2c_LDADD and
+	format into SUBDIRS.
+
+	* tools/d2c/bits/manager.c:
+	* tools/d2c/coder.c:
+	* tools/d2c/coder.h:
+	* tools/d2c/d2c.mk:
+	* tools/d2c/d2c_genmakefile.sh:
+	Introduce a format switch to distinguish different kinds of definitions.
+
+	* tools/d2c/format/Makefile.am:
+	* tools/d2c/format/decl.h:
+	* tools/d2c/format/grammar.y:
+	* tools/d2c/format/manager.c:
+	* tools/d2c/format/manager.h:
+	* tools/d2c/format/tokens.l:
+	New entries: handle a '@format' keyword.
+
+	* tools/d2c/grammar.y:
+	* tools/d2c/pproc.c:
+	* tools/d2c/pproc.h:
+	* tools/d2c/spec.c:
+	* tools/d2c/spec.h:
+	* tools/d2c/tokens.l:
+	Introduce a format switch to distinguish different kinds of definitions.
+
+16-01-30  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/arch/dalvik/instruction-int.h:
 	* src/arch/dalvik/instruction.c:
 	* src/arch/dalvik/instruction.h:
diff --git a/configure.ac b/configure.ac
index 1d61cc8..948d612 100644
--- a/configure.ac
+++ b/configure.ac
@@ -362,6 +362,7 @@ AC_CONFIG_FILES([Makefile
                  tools/d2c/args/Makefile
                  tools/d2c/bits/Makefile
                  tools/d2c/conv/Makefile
+                 tools/d2c/format/Makefile
                  tools/d2c/hooks/Makefile
                  tools/d2c/rules/Makefile
                  tools/d2c/syntax/Makefile
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index 5483f92..607b27f 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -5,6 +5,8 @@ include ../../../../../tools/d2c/d2c.mk
 D2C_BIN = ../../../../../tools/d2c/d2c
 GEN_BIN = ../../../../../tools/d2c/d2c_genmakefile.sh
 
+D2C_TYPE = raw
+
 D2C_OUTDIR = $(PWD)/..
 
 D2C_ARCH = armv7
@@ -23,6 +25,25 @@ D2C_MACROS =											\
     -M SignExtend=sign_extend_armv7_imm					\
     -M SetInsFlag=g_arch_instruction_set_flag
 
+
+FIXED_C_INCLUDES = \
+	\n\#include \"..\/helpers.h\" \
+	\n\#include \"..\/instruction.h\" \
+	\n\#include \"..\/fetch.h\" \
+	\n\#include \"..\/post.h\" \
+	\n\#include \"..\/..\/instruction.h\" \
+	\n\#include \"..\/..\/link.h\" \
+	\n\#include \"..\/..\/..\/link.h\" \
+	\n\#include \"..\/..\/..\/..\/common\/bconst.h\" \
+	\n\n
+
+FIXED_H_INCLUDES = \
+        \n\#include \<stdint.h\> \
+        \n \
+        \n\#include \"..\/..\/..\/instruction.h\" \
+        \n\n
+
+
 ARMV7_DEFS = 							\
 	adc_A881.d							\
 	adc_A882.d							\
@@ -101,25 +122,11 @@ ARMV7_DEFS = 							\
 	subs_B9320.d
 
 
-all: $(ARMV7_DEFS:.d=.g) fmk.done fix_includes_in_c_templates fix_includes_in_h_templates untabify_disass
+all: $(ARMV7_DEFS:.d=.g) fmk.done d2c_final_rules
 
 fmk.done: $(ARMV7_DEFS)
 	$(GEN_BIN) ../opcodes/ ../opdefs/.gen ../../../../../tools/d2c/globalgen.mk arm thumb_32 thumb_16
 	touch $@
 
-fix_includes_in_c_templates:
-	@for f in `find .gen/ -name '*tmpl.c'`; do			\
-		if grep -q '##INCLUDES##' $$f; then				\
-			$(fix_verbose)sed -i 's/##INCLUDES##/\n#include "..\/helpers.h"\n#include "..\/instruction.h"\n#include "..\/fetch.h"\n#include "..\/post.h"\n#include "..\/..\/instruction.h"\n#include "..\/..\/link.h"\n#include "..\/..\/..\/link.h"\n#include "..\/..\/..\/..\/common\/bconst.h"\n\n/' $$f;	\
-		fi;												\
-	done
-
-fix_includes_in_h_templates:
-	@for f in `find .gen/ -name '*tmpl.h'`; do			\
-		if grep -q '##INCLUDES##' $$f; then				\
-			$(fix_verbose)sed -i 's/##INCLUDES##/#include\ <stdint.h>\n\n#include "..\/..\/..\/instruction.h"/' $$f ;	\
-		fi;												\
-	done
-
 clean:
 	rm -rf $(ARMV7_DEFS:.d=.g) .gen fmk.done
diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am
index e89384f..dc4fdf8 100644
--- a/tools/d2c/Makefile.am
+++ b/tools/d2c/Makefile.am
@@ -33,6 +33,7 @@ d2c_SOURCES =							\
 d2c_LDADD =								\
 	bits/libd2cbits.la					\
 	conv/libd2cconv.la					\
+	format/libd2cformat.la				\
 	hooks/libd2chooks.la				\
 	rules/libd2crules.la				\
 	syntax/libd2csyntax.la				\
@@ -43,4 +44,4 @@ d2c_LDADD =								\
 CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
 
 
-SUBDIRS = args bits conv hooks rules syntax
+SUBDIRS = args bits conv format hooks rules syntax
diff --git a/tools/d2c/bits/manager.c b/tools/d2c/bits/manager.c
index db6392d..cc2783b 100644
--- a/tools/d2c/bits/manager.c
+++ b/tools/d2c/bits/manager.c
@@ -282,9 +282,9 @@ raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : spec    = spécification servant de base à l'opération.       *
-*                fd      = descripteur d'un flux ouvert en écriture.          *
-*                wide    = taille des mots manipulés (en bits).               *
+*  Paramètres  : spec = spécification servant de base à l'opération.          *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
+*                wide = taille des mots manipulés (en bits).                  *
 *                                                                             *
 *  Description : Déclare les variables C associées aux champs de bits.        *
 *                                                                             *
@@ -309,8 +309,8 @@ bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : spec    = spécification servant de base à l'opération.       *
-*                fd      = descripteur d'un flux ouvert en écriture.          *
+*  Paramètres  : spec = spécification servant de base à l'opération.          *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
 *                                                                             *
 *  Description : Vérifie que les bits fixes correspondent au masque attendu.  *
 *                                                                             *
@@ -353,8 +353,8 @@ bool check_bits_correctness(const coding_bits *bits, int fd)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : spec    = spécification servant de base à l'opération.       *
-*                fd      = descripteur d'un flux ouvert en écriture.          *
+*  Paramètres  : spec = spécification servant de base à l'opération.          *
+*                fd   = descripteur d'un flux ouvert en écriture.             *
 *                                                                             *
 *  Description : Définit les variables C associées aux champs de bits.        *
 *                                                                             *
diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c
index 83910aa..869461f 100644
--- a/tools/d2c/coder.c
+++ b/tools/d2c/coder.c
@@ -47,14 +47,18 @@
 struct _rented_coder
 {
     const char *input;                      /* Fichier de définitions      */
+    InputOutputType type;                   /* Type des définitions (E/S)  */
     const char *outdir;                     /* Lieu d'enregistrement       */
     const char *arch;                       /* Architecture à traiter      */
     const char *header;                     /* En-tête pour les en-têtes   */
+    const char *const_prefix;               /* Préfixe pour les opérandes  */
 
     pre_processor *pp;                      /* Pré-processeur avec macros  */
 
     char *copyright;                        /* Récupération des droits     */
     char *ins;                              /* Désignation humaine         */
+    char separator;                         /* Caractère de séparation     */
+    char *raw_details;                      /* Eventuels compléments bruts */
     char *details;                          /* Eventuels compléments       */
 
     encoding_spec **specs;                  /* Définitions déjà en place   */
@@ -89,6 +93,9 @@ static int create_code_file(const rented_coder *, const char *, const char *, co
 /* Ecrit une partie des fonctions issues des spécifications. */
 static bool dump_all_matching_specs_in_coder(const rented_coder *, const string_exch *, int, int);
 
+/* Ecrit une partie des fonctions issues des spécifications. */
+static bool dump_all_matching_specs_from_format(const rented_coder *, const string_exch *, int, int);
+
 
 
 /* ---------------------------------------------------------------------------------- */
@@ -144,8 +151,11 @@ void delete_coder(rented_coder *coder)
     if (coder->ins != NULL)
         free(coder->ins);
 
-    if (coder->details != NULL)
+    if (coder->raw_details != NULL)
+    {
+        free(coder->raw_details);
         free(coder->details);
+    }
 
     for (i = 0; i < coder->specs_count; i++)
         delete_encoding_spec(coder->specs[i]);
@@ -174,7 +184,15 @@ void delete_coder(rented_coder *coder)
 
 bool do_basic_checks_with_coder(const rented_coder *coder)
 {
-    return (coder->outdir != NULL && coder->arch != NULL && coder->header != NULL);
+    bool result;                            /* Validité à retourner        */
+
+    result = coder->type != IOT_UNDEFINED && coder->outdir != NULL;
+    result &= coder->arch != NULL && coder->header != NULL;
+
+    if (coder->type == IOT_FORMAT)
+        result &= (coder->const_prefix != NULL);
+
+    return result;
 
 }
 
@@ -220,6 +238,26 @@ void set_coder_input_file(rented_coder *coder, const char *input)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : coder = gestion par la machine en remplacement de l'humain.  *
+*                type  = type de définition à attendre.                       *
+*                                                                             *
+*  Description : Spécifie le type de format à prendre en compte (E/S).        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_coder_input_type(rented_coder *coder, InputOutputType type)
+{
+    coder->type = type;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : coder  = gestion par la machine en remplacement de l'humain. *
 *                outdir = répertoire de génération des fichiers.              *
 *                                                                             *
@@ -280,6 +318,26 @@ void set_coder_header_base(rented_coder *coder, const char *header)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : coder  = gestion par la machine en remplacement de l'humain. *
+*                prefix = préfixe pour les types d'opérandes.                 *
+*                                                                             *
+*  Description : Définit le préfixe pour les opérandes chargées par format.   *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_coder_const_prefix(rented_coder *coder, const char *prefix)
+{
+    coder->const_prefix = prefix;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : coder = gestion par la machine en remplacement de l'humain.  *
 *                                                                             *
 *  Description : Fournit le pré-processeur du compilateur.                    *
@@ -302,6 +360,7 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder)
 *  Paramètres  : coder   = gestion par la machine en remplacement de l'humain.*
 *                copy    = droits de copie en anglais.                        *
 *                ins     = désignation humaine de l'instruction.              *
+*                sep     = caractère de séparation avant les détails.         *
 *                details = compléments d'informations éventuels ou NULL.      *
 *                                                                             *
 *  Description : Enregistre les contours d'une instruction d'assemblage.      *
@@ -312,11 +371,23 @@ pre_processor *get_coder_pre_proc(const rented_coder *coder)
 *                                                                             *
 ******************************************************************************/
 
-void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, const char *details)
+void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, char sep, const char *details)
 {
     coder->copyright = copy;
     coder->ins = make_string_lower(ins);
-    coder->details = (details != NULL ? make_callable(details, true) : strdup(""));
+
+    coder->separator = sep;
+
+    if (details != NULL)
+    {
+        coder->raw_details = strdup(details);
+        coder->details = make_callable(details, true);
+    }
+    else
+    {
+        coder->raw_details = strdup("");
+        coder->details = strdup("");
+    }
 
 }
 
@@ -366,7 +437,8 @@ void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index)
 
     spec = coder->cur_spec;
 
-    define_encoding_spec_code_name(spec, prefix, index);
+    if (prefix != NULL)
+        define_encoding_spec_code_name(spec, prefix, index);
 
     coder->specs = (encoding_spec **)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec *));
     coder->specs[coder->specs_count - 1] = spec;
@@ -494,9 +566,18 @@ static char *build_template_filename(const rented_coder *coder, const char *pref
     char *result;                           /* Chaîne construite à renvoyer*/
     size_t length;                          /* Taille du nom de fichier    */
 
-    length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3;
-    result = (char *)calloc(length, sizeof(char));
-    snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext);
+    if (prefix == NULL)
+    {
+        length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(name) + 3;
+        result = (char *)calloc(length, sizeof(char));
+        snprintf(result, length, ".gen/%s.tmpl.%c", name, ext);
+    }
+    else
+    {
+        length = strlen(".gen") + 1 + strlen("template") + 1 + strlen(prefix) + 1 + strlen(name) + 3;
+        result = (char *)calloc(length, sizeof(char));
+        snprintf(result, length, ".gen/%s.%s.tmpl.%c", prefix, name, ext);
+    }
 
     return result;
 
@@ -523,6 +604,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,
     char *pathname;                         /* Chemin d'accès à constituer */
     bool exist;                             /* Note une présence établie   */
     int fd;                                 /* Flux ouvert pour création   */
+    const char *valid_prefix;               /* Prefix vide au besoin       */
     char *uprefix;                          /* Préfixe en majuscule        */
     char *uname;                            /* Nom en majuscule            */
 
@@ -545,11 +627,13 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,
 
     if (fd != -1)
     {
-        write_owner_comments(coder, fd, prefix, name, ext);
+        valid_prefix = prefix != NULL ? prefix : "";
+
+        write_owner_comments(coder, fd, valid_prefix, name, ext);
 
         if (ext == 'h')
         {
-            uprefix = make_string_upper(strdup(prefix));
+            uprefix = make_string_upper(strdup(valid_prefix));
             uname = make_string_upper(strdup(name));
 
             dprintf(fd, "#ifndef %s_%s%s_H\n", coder->header, uprefix, uname);
@@ -568,7 +652,7 @@ static bool create_template_file(const rented_coder *coder, const char *prefix,
         }
         else
         {
-            dprintf(fd, "#include \"%sopcodes.h\"\n", prefix);
+            dprintf(fd, "#include \"%sopcodes.h\"\n", valid_prefix);
             dprintf(fd, "\n");
             dprintf(fd, "##INCLUDES##\n");
 
@@ -611,9 +695,18 @@ static char *build_code_filename(const rented_coder *coder, const char *input, c
     point = strstr(orig, ".");
     if (point != NULL) *point = '\0';
 
-    length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3;
-    result = (char *)calloc(length, sizeof(char));
-    snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext);
+    if (prefix == NULL)
+    {
+        length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(name) + 3;
+        result = (char *)calloc(length, sizeof(char));
+        snprintf(result, length, ".gen/%s.%s.%c", orig, name, ext);
+    }
+    else
+    {
+        length = strlen(".gen") + 1 + strlen(orig) + 1 + strlen(prefix) + 1 + strlen(name) + 3;
+        result = (char *)calloc(length, sizeof(char));
+        snprintf(result, length, ".gen/%s.%s.%s.%c", orig, prefix, name, ext);
+    }
 
     free(orig);
 
@@ -807,7 +900,22 @@ bool dump_all_routines_using_coder(const rented_coder *coder)
 
             /* Production de code... */
 
-            result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd);
+            switch (coder->type)
+            {
+                case IOT_UNDEFINED:
+                    assert(false);
+                    result = false;
+                    break;
+
+                case IOT_RAW:
+                    result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd);
+                    break;
+
+                case IOT_FORMAT:
+                    result = dump_all_matching_specs_from_format(coder, encoding, header_fd, code_fd);
+                    break;
+
+            }
 
             close(header_fd);
             close(code_fd);
@@ -899,7 +1007,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
         dprintf(cfd, "*\n");
 
     dprintf(cfd, "                                                                              *\n");
-    dprintf(cfd, "*  Retour      : Bilan de l'opération.                                        *\n");
+    dprintf(cfd, "*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *\n");
     dprintf(cfd, "*                                                                             *\n");
     dprintf(cfd, "*  Remarques   : -                                                            *\n");
     dprintf(cfd, "*                                                                             *\n");
@@ -942,3 +1050,111 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : coder    = gestion par la machine en remplacement d'humain.  *
+*                encoding = sélection de l'encodage à traiter.                *
+*                hfd      = flux ouvert en écriture pour les déclarations.    *
+*                cfd      = flux ouvert en écriture pour les définitions.     *
+*                                                                             *
+*  Description : Ecrit une partie des fonctions issues des spécifications.    *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static bool dump_all_matching_specs_from_format(const rented_coder *coder, const string_exch *encoding, int hfd, int cfd)
+{
+    bool result;                            /* Bilan à retourner           */
+    char *keyword;                          /* Mot clef appelable en code  */
+    size_t maxlen;                          /* Taille à compléter          */
+    encoding_spec *spec;                    /* Définition à traiter        */
+
+    keyword = make_callable(coder->ins, false);
+
+    /* Désassemblage : déclaration */
+
+    dprintf(hfd, "/* Décode une instruction de type '%s'. */\n", coder->ins);
+
+    if (encoding->dest == NULL)
+        dprintf(hfd, "GArchInstruction *%s_read_instr_%s%s",
+                coder->arch, keyword, coder->details);
+    else
+        dprintf(hfd, "GArchInstruction *%s_read_%sinstr_%s%s",
+                coder->arch, encoding->dest, keyword, coder->details);
+
+    dprintf(hfd, "(");
+    dprintf(hfd, "const GArchProcessor *, GProcContext *, const GBinContent *, ");
+    dprintf(hfd, "vmpa2t *, GExeFormat *");
+    dprintf(hfd, ");\n");
+
+    dprintf(hfd, "\n");
+
+    /* Désassemblage : définitions */
+
+    dprintf(cfd, "\n");
+
+    dprintf(cfd, "/******************************************************************************\n");
+    dprintf(cfd, "*                                                                             *\n");
+    dprintf(cfd, "*  Paramètres  : proc    = processeur de l'architecture d'exécution.          *\n");
+    dprintf(cfd, "*                ctx     = contexte associé à la phase de désassemblage.      *\n");
+    dprintf(cfd, "*                content = flux de données à analyser.                        *\n");
+    dprintf(cfd, "*                pos     = position courante dans ce flux. [OUT]              *\n");
+    dprintf(cfd, "*                format  = format du fichier contenant le code.               *\n");
+    dprintf(cfd, "*                                                                             *\n");
+    dprintf(cfd, "*  Description : Décode une instruction de type '%s'.", coder->ins);
+
+    maxlen = 28 - strlen(coder->ins);
+
+    if (maxlen < 28)
+        dprintf(cfd, "%*s\n", (int)maxlen, "*");
+    else
+        dprintf(cfd, "*\n");
+
+    dprintf(cfd, "                                                                              *\n");
+    dprintf(cfd, "*  Retour      : Instruction mise en place ou NULL en cas d'échec.            *\n");
+    dprintf(cfd, "*                                                                             *\n");
+    dprintf(cfd, "*  Remarques   : -                                                            *\n");
+    dprintf(cfd, "*                                                                             *\n");
+    dprintf(cfd, "******************************************************************************/\n");
+
+    dprintf(cfd, "\n");
+
+    if (encoding->dest == NULL)
+        dprintf(cfd, "GArchInstruction *%s_read_instr_%s%s",
+                coder->arch, keyword, coder->details);
+    else
+        dprintf(cfd, "GArchInstruction *%s_read_%sinstr_%s%s",
+                coder->arch, encoding->dest, keyword, coder->details);
+
+    dprintf(cfd, "(");
+    dprintf(cfd, "const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, ");
+    dprintf(cfd, "vmpa2t *pos, GExeFormat *format");
+    dprintf(cfd, ")");
+
+    dprintf(cfd, "\n");
+    dprintf(cfd, "{");
+    dprintf(cfd, "\n");
+
+    assert(coder->specs_count == 1);
+
+    spec = coder->specs[0];
+
+    assert(has_encoding_spec_prefix(spec, encoding->src));
+
+    result = write_encoding_spec_format_disass(spec, cfd, coder->arch, encoding->dest,
+                                               coder->ins, coder->separator, coder->raw_details,
+                                               coder->pp, coder->const_prefix);
+
+    dprintf(cfd, "}\n");
+    dprintf(cfd, "\n");
+
+    free(keyword);
+
+    return result;
+
+}
diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h
index d9f0f0e..7ba88bc 100644
--- a/tools/d2c/coder.h
+++ b/tools/d2c/coder.h
@@ -41,6 +41,16 @@ typedef struct _rented_coder rented_coder;
 /* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */
 
 
+/* Type d'entrée/sortie attendues */
+typedef enum _InputOutputType
+{
+    IOT_UNDEFINED,                          /* Type non défini             */
+    IOT_RAW,                                /* Lecture de contenu brut     */
+    IOT_FORMAT                              /* Définition d'opérandes      */
+
+} InputOutputType;
+
+
 /* Débute la définition d'une fonction de désassemblage. */
 rented_coder *create_coder(void);
 
@@ -56,6 +66,9 @@ const char *get_coder_input_file(const rented_coder *);
 /* Spécifie le fichier de définition à prendre en entrée. */
 void set_coder_input_file(rented_coder *, const char *);
 
+/* Spécifie le type de format à prendre en compte (E/S). */
+void set_coder_input_type(rented_coder *, InputOutputType);
+
 /* Spécifie le répertoire de base pour les sorties de code. */
 void set_coder_output_directory(rented_coder *, const char *);
 
@@ -65,11 +78,14 @@ void set_coder_arch(rented_coder *, const char *);
 /* Définit la base des protections des fichiers d'en-tête. */
 void set_coder_header_base(rented_coder *, const char *);
 
+/* Définit le préfixe pour les opérandes chargées par format. */
+void set_coder_const_prefix(rented_coder *, const char *);
+
 /* Fournit le pré-processeur du compilateur. */
 pre_processor *get_coder_pre_proc(const rented_coder *);
 
 /* Enregistre les contours d'une instruction d'assemblage. */
-void save_notes_for_coder(rented_coder *, char *, char *, const char *);
+void save_notes_for_coder(rented_coder *, char *, char *, char, const char *);
 
 
 
diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk
index b0b7b92..72269b7 100644
--- a/tools/d2c/d2c.mk
+++ b/tools/d2c/d2c.mk
@@ -9,19 +9,42 @@ fix_verbose = $(fix_verbose_@AM_V@)
 fix_verbose_ = $(fix_verbose_@AM_DEFAULT_V@)
 fix_verbose_0 = echo "  FIX     " `basename $$f`;
 
-# D2C_BIN = 
-# D2C_OUTDIR = 
-# D2C_ARCH = 
-# D2C_HEADER = 
-# D2C_ENCODINGS = 
-# D2C_MACROS = 
+
+# D2C_BIN =
+# D2C_TYPE =
+# D2C_OUTDIR =
+# D2C_ARCH =
+# D2C_HEADER =
+# D2C_ENCODINGS =
+# D2C_MACROS =
+# D2C_PREFIX =
+
+# FIXED_C_INCLUDES =
+# FIXED_H_INCLUDES =
+
 
 SUFFIXES = .g
 
 .d.g:
-	$(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS)
+	$(d2c_verbose)$(D2C_BIN) -i $< -t $(D2C_TYPE) -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) -p $(D2C_PREFIX)
 	@touch $@
 
+d2c_final_rules: fix_includes_in_c_templates fix_includes_in_h_templates untabify_disass
+
+fix_includes_in_c_templates:
+	for f in `find .gen/ -name '*tmpl.c'`; do			\
+		if grep -q '##INCLUDES##' $$f; then				\
+			$(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_C_INCLUDES)/' $$f;	\
+		fi;												\
+	done
+
+fix_includes_in_h_templates:
+	@for f in `find .gen/ -name '*tmpl.h'`; do			\
+		if grep -q '##INCLUDES##' $$f; then				\
+			$(fix_verbose)sed -i 's/##INCLUDES##/$(FIXED_H_INCLUDES)/' $$f ;	\
+		fi;												\
+	done
+
 # Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t
 untabify_disass:
 	@find .gen/ -name '*[ch]' -exec grep -q $$'\t' {} \; -exec sed -i 's/\t/    /g' {} \;
diff --git a/tools/d2c/d2c_genmakefile.sh b/tools/d2c/d2c_genmakefile.sh
index 2338b6d..7911d04 100755
--- a/tools/d2c/d2c_genmakefile.sh
+++ b/tools/d2c/d2c_genmakefile.sh
@@ -29,19 +29,31 @@ $echo >> ${MAKEFILE_TMP}
 $echo "include ${globalmk}" >> ${MAKEFILE_TMP}
 $echo >> ${MAKEFILE_TMP}
 
-OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d . -f 3 | sort | uniq`
+if [ "$1" = "-" ]; then
+    OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f2 | sort | uniq`
+else
+    OPCODES=`find ${input} -name '*c' -and -not -name '*.tmpl.c' -exec basename {} \; | cut -d. -f3 | sort | uniq`
+fi
 
 # Génération des en-têtes de décodage
 
 for arch in $*;
 do
-    $echo -n "${arch}_HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+    if [ ${arch} = "-" ]; then
+        arch_name=""
+        arch_name_dotted=""
+    else
+        arch_name="${arch}_"
+        arch_name_dotted="${arch}_."
+    fi
+
+    $echo -n "${arch_name}HEADER_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
 
     has_header=""
 
     for op in $OPCODES;
     do
-        template="${input}/*${arch}_.${op}.c"
+        template="${input}/*.${arch_name_dotted}${op}.c"
 
         sources=`ls $template 2> /dev/null`
 
@@ -62,8 +74,8 @@ do
     $echo >> ${MAKEFILE_TMP}
     $echo >> ${MAKEFILE_TMP}
 
-    $echo -n "${arch}_opcodes.h: " >> ${MAKEFILE_TMP}
-    $echo "\$(${arch}_HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+    $echo -n "${arch_name}opcodes.h: " >> ${MAKEFILE_TMP}
+    $echo "\$(${arch_name}HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
 
     if [ -z "${has_header}" ]; then
 
@@ -71,7 +83,7 @@ do
 
     else
 
-        $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP}
+        $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}opcodes.tmpl.h > \$@" >> ${MAKEFILE_TMP}
         $echo -e "\t\$(cgen_verbose)cat \$^ >> \$@" >> ${MAKEFILE_TMP}
         $echo -e "\t\$(cfini_verbose)echo >> \$@" >> ${MAKEFILE_TMP}
         $echo -en "\t\$(cfini_verbose)echo \"#endif\t /* " >> ${MAKEFILE_TMP}
@@ -93,7 +105,15 @@ for op in $OPCODES;
 do
     for arch in $*;
     do
-        template="${input}/*${arch}_.${op}.c"
+        if [ ${arch} = "-" ]; then
+            arch_name=""
+            arch_name_dotted=""
+        else
+            arch_name="${arch}_"
+            arch_name_dotted="${arch}_."
+        fi
+
+        template="${input}/*.${arch_name_dotted}${op}.c"
 
         sources=`ls $template 2> /dev/null`
 
@@ -101,7 +121,7 @@ do
             continue
         fi
 
-        $echo -n "${op}_${arch}_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+        $echo -n "${op}_${arch_name}FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
 
         for src in ${sources};
         do
@@ -112,13 +132,13 @@ do
         $echo >> ${MAKEFILE_TMP}
         $echo >> ${MAKEFILE_TMP}
 
-        $echo -n "${arch}_${op}.c: " >> ${MAKEFILE_TMP}
-        $echo -n "\$(${op}_${arch}_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
-        $echo " ${arch}_opcodes.h" >> ${MAKEFILE_TMP}
+        $echo -n "${arch_name}${op}.c: " >> ${MAKEFILE_TMP}
+        $echo -n "\$(${op}_${arch_name}FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+        $echo " ${arch_name}opcodes.h" >> ${MAKEFILE_TMP}
 
-        $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP}
+        $echo -e "\t\$(cini_verbose)cat ${input}/${arch_name_dotted}${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP}
         $echo -ne "\t\$(cgen_verbose)cat \$(" >> ${MAKEFILE_TMP}
-        $echo -ne "${op}_${arch}_FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+        $echo -ne "${op}_${arch_name}FILES" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
         $echo -e ") >> \$@" >> ${MAKEFILE_TMP}
 
         $echo >> ${MAKEFILE_TMP}
@@ -135,18 +155,26 @@ $echo -n "GENERATED_FILES =" >> ${MAKEFILE_TMP}
 
 for arch in $*;
 do
+    if [ ${arch} = "-" ]; then
+        arch_name=""
+        arch_name_dotted=""
+    else
+        arch_name="${arch}_"
+        arch_name_dotted="${arch}_."
+    fi
+
     $echo -ne " \\" >> ${MAKEFILE_TMP}
-    $echo -ne "\n\t${arch}_opcodes.h" >> ${MAKEFILE_TMP}
+    $echo -ne "\n\t${arch_name}opcodes.h" >> ${MAKEFILE_TMP}
 
     for op in $OPCODES;
     do
-        template="${input}/*${arch}_.${op}.c"
+        template="${input}/*.${arch_name_dotted}${op}.c"
 
         sources=`ls $template 2> /dev/null`
 
         if [ ! -z "${sources}" ]; then
             $echo -ne " \\" >> ${MAKEFILE_TMP}
-            $echo -ne "\n\t${arch}_${op}.c" >> ${MAKEFILE_TMP}
+            $echo -ne "\n\t${arch_name}${op}.c" >> ${MAKEFILE_TMP}
             continue
         fi
 
diff --git a/tools/d2c/format/Makefile.am b/tools/d2c/format/Makefile.am
new file mode 100644
index 0000000..7afd98d
--- /dev/null
+++ b/tools/d2c/format/Makefile.am
@@ -0,0 +1,31 @@
+
+BUILT_SOURCES = grammar.h
+
+
+# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS
+# afin de conserver des noms de fichiers simples, ie sans le nom de la
+# bibliothèque de sortie en préfixe.
+
+AM_YFLAGS = -v -d -p format_
+
+AM_LFLAGS = -P format_ -o lex.yy.c --header-file=tokens.h			\
+			-Dyylval=format_lval -Dyyget_lineno=format_get_lineno 	\
+			-Dyy_scan_string=format__scan_string					\
+			-Dyy_delete_buffer=format__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES  = libd2cformat.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2cformat_la_SOURCES =				\
+	decl.h								\
+	manager.h manager.c					\
+	tokens.l							\
+	grammar.y
+
+
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
diff --git a/tools/d2c/format/decl.h b/tools/d2c/format/decl.h
new file mode 100644
index 0000000..0b7775a
--- /dev/null
+++ b/tools/d2c/format/decl.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * decl.h - déclarations de prototypes utiles
+ *
+ * Copyright (C) 2016 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _TOOLS_D2C_FORMAT_DECL_H
+#define _TOOLS_D2C_FORMAT_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données relatives à une définition de format. */
+bool load_format_from_raw_line(operands_format *, const char *);
+
+
+
+#endif  /* _TOOLS_D2C_BITS_DECL_H */
diff --git a/tools/d2c/format/grammar.y b/tools/d2c/format/grammar.y
new file mode 100644
index 0000000..062d616
--- /dev/null
+++ b/tools/d2c/format/grammar.y
@@ -0,0 +1,107 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(operands_format *, char *);
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+
+}
+
+
+%union {
+
+    char *string;                           /* Chaîne de caractères        */
+
+}
+
+
+%define api.pure full
+
+%parse-param { operands_format *format }
+
+%code provides {
+
+#define YY_DECL \
+    int format_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token OPS_TYPE
+
+%type <string> OPS_TYPE
+
+
+
+%%
+
+
+type : OPS_TYPE { set_operands_format_type(format, $1); }
+
+
+%%
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = structure impliquée dans le processus.              *
+*                msg    = message d'erreur.                                   *
+*                                                                             *
+*  Description : Affiche un message d'erreur suite à l'analyse en échec.      *
+*                                                                             *
+*  Retour      : 0                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static int yyerror(operands_format *format, char *msg)
+{
+	printf("bits yyerror line %d: %s\n", yyget_lineno(), msg);
+
+	return 0;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = structure à constituer à partir de données lues.    *
+*                raw    = données brutes à analyser.                          *
+*                                                                             *
+*  Description : Interprête des données relatives à une définition de format. *
+*                                                                             *
+*  Retour      : true si l'opération s'est bien déroulée, false sinon.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool load_format_from_raw_line(operands_format *format, const char *raw)
+{
+    bool result;                            /* Bilan à faire remonter      */
+    YY_BUFFER_STATE state;                  /* Support d'analyse           */
+    int status;                             /* Bilan de l'analyse          */
+
+    state = yy_scan_string(raw);
+
+    status = yyparse(format);
+
+    result = (status == 0);
+
+    yy_delete_buffer(state);
+
+    return result;
+
+}
diff --git a/tools/d2c/format/manager.c b/tools/d2c/format/manager.c
new file mode 100644
index 0000000..070b70c
--- /dev/null
+++ b/tools/d2c/format/manager.c
@@ -0,0 +1,145 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.c - enregistrement de la définition des opérandes attendus
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "manager.h"
+
+
+#include <malloc.h>
+
+
+#include "../helpers.h"
+
+
+
+/* Mémorisation de la définition d'opérandes */
+struct _operands_format
+{
+    char *type;                             /* Définitions des opérandes   */
+
+};
+
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Crée un nouveau gestionnaire de définitions d'opérandes.     *
+*                                                                             *
+*  Retour      : Nouvelle structure prête à emploi.                           *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+operands_format *create_operands_format(void)
+{
+    operands_format *result;                /* Définition vierge à renvoyer*/
+
+    result = (operands_format *)calloc(1, sizeof(operands_format));
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = gestionnaire de définition d'opérandes à libérer.   *
+*                                                                             *
+*  Description : Supprime de la mémoire un gestionnaire de définitions.       *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void delete_operands_format(operands_format *format)
+{
+    if (format->type != NULL)
+        free(format->type);
+
+    free(format);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : format = gestionnaire de définition d'opérandes à traiter.   *
+*                type   = définitions des opérandes à charger.                *
+*                                                                             *
+*  Description : Précise le type d'opérandes dont la définition est à charger.*
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_operands_format_type(operands_format *format, char *type)
+{
+    if (format->type != NULL)
+        free(format->type);
+
+    format->type = make_string_upper(type);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : spec   = spécification servant de base à l'opération.        *
+*                fd     = descripteur d'un flux ouvert en écriture.           *
+*                arch   = architecture visée par l'opération.                 *
+*                prefix = préfixe pour le type de définitions d'opérandes.    *
+*                exit   = exprime le besoin d'une voie de sortie. [OUT]       *
+*                                                                             *
+*  Description : Définit le chargement des opérandes prévus par la définition.*
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool define_operands_loading(const operands_format *format, int fd, const char *arch, const char *prefix, bool *exit)
+{
+    if (format->type == NULL)
+    {
+        fprintf(stderr, "Error: no type defined for operands.\n");
+        return false;
+    }
+
+    *exit = true;
+
+    dprintf(fd, "\tif (!%s_read_operands(result, format, content, pos, endian, %s%s))\n",
+            arch, prefix, format->type);
+
+    dprintf(fd, "\t\tgoto bad_exit;\n");
+    dprintf(fd, "\n");
+
+    return true;
+
+}
diff --git a/tools/d2c/format/manager.h b/tools/d2c/format/manager.h
new file mode 100644
index 0000000..4555710
--- /dev/null
+++ b/tools/d2c/format/manager.h
@@ -0,0 +1,50 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour l'enregistrement de la définition des opérandes attendus
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ *  This file is part of Chrysalide.
+ *
+ *  OpenIDA is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  OpenIDA is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _TOOLS_D2C_FORMAT_MANAGER_H
+#define _TOOLS_D2C_FORMAT_MANAGER_H
+
+
+#include <stdbool.h>
+
+
+
+/* Mémorisation de la définition d'opérandes */
+typedef struct _operands_format operands_format;
+
+
+/* Crée un nouveau gestionnaire de définitions d'opérandes. */
+operands_format *create_operands_format(void);
+
+/* Supprime de la mémoire un gestionnaire de définitions. */
+void delete_operands_format(operands_format *);
+
+/* Précise le type d'opérandes dont la définition est à charger. */
+void set_operands_format_type(operands_format *, char *);
+
+/* Définit le chargement des opérandes prévus par la définition. */
+bool define_operands_loading(const operands_format *, int, const char *, const char *, bool *);
+
+
+
+#endif  /* _TOOLS_D2C_FORMAT_MANAGER_H */
diff --git a/tools/d2c/format/tokens.l b/tools/d2c/format/tokens.l
new file mode 100644
index 0000000..12ca7f0
--- /dev/null
+++ b/tools/d2c/format/tokens.l
@@ -0,0 +1,26 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option noyy_top_state
+
+%x bsize
+
+
+%%
+
+
+" "                     { }
+
+[A-Za-z0-9_]*   { yylvalp->string = strdup(yytext); return OPS_TYPE; }
+
+
+%%
diff --git a/tools/d2c/grammar.y b/tools/d2c/grammar.y
index 986edd7..02b2671 100644
--- a/tools/d2c/grammar.y
+++ b/tools/d2c/grammar.y
@@ -30,11 +30,23 @@ static void *map_input_data(const char *, size_t *);
 #include "args/decl.h"
 #include "bits/decl.h"
 #include "conv/decl.h"
+#include "format/decl.h"
 #include "hooks/decl.h"
 #include "rules/decl.h"
 #include "syntax/decl.h"
 
 
+#define handle_coder_format(c, r)                           \
+    ({                                                      \
+        encoding_spec *__spec;                              \
+        operands_format *__format;                          \
+        bool __status;                                      \
+        __spec = get_current_encoding_spec(c);              \
+        __format = get_format_in_encoding_spec(__spec);     \
+        __status = load_format_from_raw_line(__format, r);  \
+        if (!__status) YYABORT;                             \
+    })
+
 #define handle_coder_bits(c, e, r)                          \
     ({                                                      \
         encoding_spec *__spec;                              \
@@ -94,6 +106,7 @@ static void *map_input_data(const char *, size_t *);
 
 %union {
 
+    char character;                         /* Simple caractère isolé      */
     char *string;                           /* Chaîne de caractères #1     */
     const char *cstring;                    /* Chaîne de caractères #2     */
 
@@ -124,12 +137,13 @@ YY_DECL;
 
 %token COPYRIGHT
 %token TITLE
-%token INS_NAME INS_DETAILS
+%token INS_NAME INS_SEP INS_DETAILS
 
 %token ENCODING
 %token TYPE NUMBER
 %token ENC_START ENC_END
 
+%token FORMAT
 %token WORD HALF
 %token SYNTAX
 %token CONV
@@ -140,6 +154,7 @@ YY_DECL;
 
 
 %type <string> COPYRIGHT INS_NAME
+%type <character> INS_SEP
 %type <cstring> INS_DETAILS
 
 %type <string> TYPE
@@ -153,14 +168,27 @@ YY_DECL;
 
 input : name encodings { if (!dump_all_routines_using_coder(coder)) YYABORT; }
 
-name : COPYRIGHT TITLE INS_NAME             { save_notes_for_coder(coder, $1, $3, NULL); }
-     | COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); }
+name : COPYRIGHT TITLE INS_NAME                     { save_notes_for_coder(coder, $1, $3, '\0', NULL); }
+     | COPYRIGHT TITLE INS_NAME INS_SEP INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4, $5); }
 
 
 encodings : /* empty */
           | encoding encodings
 
-encoding : ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); }
+encoding : ENCODING TYPE NUMBER format_content { push_encoding_spec(coder, $2, $3); }
+         | ENCODING format_content { push_encoding_spec(coder, NULL, -1); }
+         | ENCODING TYPE NUMBER content { push_encoding_spec(coder, $2, $3); }
+
+
+/* Définitions à l'aide d'un format défini */
+
+format_content : /* empty */
+               | format format_content
+
+format : FORMAT RAW_LINE { handle_coder_format(coder, $2); }
+
+
+/* Définitions à l'aide de données brutes */
 
 
 content : /* empty */
@@ -170,7 +198,6 @@ content : /* empty */
         | hooks content
         | rules content
 
-
 bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); }
          | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); }
 
@@ -225,7 +252,7 @@ static void show_usage(const char *argv0)
 {
     printf("\n");
 
-    printf("Usage: %s [options] < file\n", argv0);
+    printf("Usage: %s [options]\n", argv0);
 
     printf("\n");
 
@@ -234,11 +261,14 @@ static void show_usage(const char *argv0)
     printf("\n");
 
     printf("\t-h | --help\t\t\tDisplay this messsage.\n");
+    printf("\t-i | --input <file>\t\tProvide the input file containing the description.\n");
+    printf("\t-t | --type <raw|format>\tSet the type of the input file.\n");
     printf("\t-d | --dir <string>\t\tSpecify the main output directory.\n");
     printf("\t-a | --arch <string>\t\tDefine the archicture to handle.\n");
     printf("\t-H | --header <string>\t\tSet the base of the #ifndef / #define game.\n");
-    printf("\t-e | --encoding <string>\tDefine encoding prefixes for files.\n");
+    printf("\t-e | --encoding <none|string>\tDefine encoding prefixes for files.\n");
     printf("\t-m | --macro <string>\t\tRegister some conversion functions.\n");
+    printf("\t-p | --prefix <string>\t\tDefine a prefix to format operand type constants (see -t).\n");
 
     printf("\n");
 
@@ -333,11 +363,13 @@ int main(int argc, char **argv)
 
         { "help",       no_argument,        NULL,   'h' },
         { "input",      required_argument,  NULL,   'i' },
+        { "type",       required_argument,  NULL,   't' },
         { "dir",        required_argument,  NULL,   'd' },
         { "arch",       required_argument,  NULL,   'a' },
         { "header",     required_argument,  NULL,   'H' },
         { "encoding",   required_argument,  NULL,   'e' },
         { "macro",      required_argument,  NULL,   'M' },
+        { "prefix",     required_argument,  NULL,   'p' },
         { NULL,         0,                  NULL,   0   }
 
     };
@@ -353,7 +385,7 @@ int main(int argc, char **argv)
 
     while (!has_error)
     {
-        ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index);
+        ret = getopt_long(argc, argv, "hi:t:d:a:H:e:M:p:", long_options, &index);   
         if (ret == -1) break;
 
         switch (ret)
@@ -366,6 +398,13 @@ int main(int argc, char **argv)
                 set_coder_input_file(coder, optarg);
                 break;
 
+            case 't':
+                if (strcmp(optarg, "raw") == 0)
+                    set_coder_input_type(coder, IOT_RAW);
+                else if (strcmp(optarg, "format") == 0)
+                    set_coder_input_type(coder, IOT_FORMAT);
+                break;
+
             case 'd':
                 set_coder_output_directory(coder, optarg);
                 break;
@@ -380,13 +419,20 @@ int main(int argc, char **argv)
 
             case 'e':
 
-                sep = strchr(optarg, '=');
-                has_error = (sep == NULL);
-
-                if (!has_error)
+                if (strcmp(optarg, "none") == 0)
+                    register_empty_encoding(get_coder_pre_proc(coder));
+ 
+                else
                 {
-                    *sep = '\0';
-                    register_encoding(get_coder_pre_proc(coder), optarg, sep + 1);
+                    sep = strchr(optarg, '=');
+                    has_error = (sep == NULL);
+
+                    if (!has_error)
+                    {
+                        *sep = '\0';
+                        register_encoding(get_coder_pre_proc(coder), optarg, sep + 1);
+                    }
+
                 }
 
                 break;
@@ -404,6 +450,10 @@ int main(int argc, char **argv)
 
                 break;
 
+            case 'p':
+                set_coder_const_prefix(coder, optarg);
+                break;
+
         }
 
     }
@@ -412,6 +462,7 @@ int main(int argc, char **argv)
     {
         show_usage(argv[0]);
         result = (need_help ? EXIT_SUCCESS : EXIT_FAILURE);
+        printf("need help ? %d  -  result = %d vs %d\n", need_help, result, EXIT_SUCCESS);
         goto exit;
     }
 
diff --git a/tools/d2c/pproc.c b/tools/d2c/pproc.c
index 8644af5..fb72774 100644
--- a/tools/d2c/pproc.c
+++ b/tools/d2c/pproc.c
@@ -92,6 +92,32 @@ void delete_pre_processor(pre_processor *pp)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : pp = pré-processeur dont le contenu est à compléter.         *
+*                                                                             *
+*  Description : Enregistre une correspondance nule en matière d'encodage.    *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void register_empty_encoding(pre_processor *pp)
+{
+    string_exch *encoding;                  /* Traduction à conserver      */
+
+    pp->encodings = (string_exch *)realloc(pp->encodings, ++pp->encodings_count * sizeof(string_exch));
+
+    encoding = &pp->encodings[pp->encodings_count - 1];
+
+    encoding->src = NULL;
+    encoding->dest = NULL;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : pp   = pré-processeur dont le contenu est à compléter.       *
 *                src  = chaîne à remplacer dans les définitions.              *
 *                dest = chaîne de remplacement.                               *
diff --git a/tools/d2c/pproc.h b/tools/d2c/pproc.h
index 2a7b6c8..a2812f8 100644
--- a/tools/d2c/pproc.h
+++ b/tools/d2c/pproc.h
@@ -47,6 +47,9 @@ pre_processor *create_pre_processor(void);
 /* Supprime de la mémoire un pré-processeur et ses macros. */
 void delete_pre_processor(pre_processor *);
 
+/* Enregistre une correspondance nule en matière d'encodage. */
+void register_empty_encoding(pre_processor *);
+
 /* Enregistre une correspondance en matière d'encodage. */
 void register_encoding(pre_processor *, const char *, const char *);
 
diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c
index 30a412a..1692fd8 100644
--- a/tools/d2c/spec.c
+++ b/tools/d2c/spec.c
@@ -40,6 +40,8 @@ struct _encoding_spec
     char *lprefix;                          /* Distinction en minuscules   */
     unsigned int index;                     /* Distinction secondaire      */
 
+    operands_format *format;                /* Définition des opérandes    */
+
     coding_bits *bits;                      /* Encodage des bits associés  */
     asm_syntax *syntax;                     /* Calligraphe d'assemblage    */
     conv_list *conversions;                 /* Conversions des données     */
@@ -68,6 +70,8 @@ encoding_spec *create_encoding_spec(void)
 
     result = (encoding_spec *)calloc(1, sizeof(encoding_spec));
 
+    result->format = create_operands_format();
+
     result->bits = create_coding_bits();
     result->syntax = create_asm_syntax();
     result->conversions = create_conv_list();
@@ -93,6 +97,8 @@ encoding_spec *create_encoding_spec(void)
 
 void delete_encoding_spec(encoding_spec *spec)
 {
+    delete_operands_format(spec->format);
+
     delete_coding_bits(spec->bits);
     delete_asm_syntax(spec->syntax);
     delete_conv_list(spec->conversions);
@@ -142,7 +148,37 @@ void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned
 
 bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix)
 {
-    return (strcmp(spec->prefix, prefix) == 0);
+    bool result;                            /* Bilan à renvoyer            */
+
+    if (spec->prefix == NULL && prefix == NULL)
+        result = true;
+
+    else if (spec->prefix != NULL && prefix != NULL)
+        result = strcmp(spec->prefix, prefix) == 0;
+
+    else
+        result = false;
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : spec = spécification d'encodage à consulter.                 *
+*                                                                             *
+*  Description : Fournit le gestionnaire des définitions d'opérandes.         *
+*                                                                             *
+*  Retour      : Structure assurant la définition des opérandes               *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+operands_format *get_format_in_encoding_spec(const encoding_spec *spec)
+{
+    return spec->format;
 
 }
 
@@ -250,7 +286,6 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *spec)
 *                subarch = sous-catégorie de cette même architecture.         *
 *                ins     = désignation première de l'instruction manipulée.   *
 *                details = particularités de l'instruction.                   *
-*                keyword = nom clef de l'instruction utilisable dans du code. *
 *                wide    = taille des mots manipulés (en bits).               *
 *                pp      = pré-processeur pour les échanges de chaînes.       *
 *                                                                             *
@@ -380,3 +415,98 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
     return result;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : spec    = spécification servant de base à l'opération.       *
+*                fd      = descripteur d'un flux ouvert en écriture.          *
+*                arch    = architecture visée par l'opération.                *
+*                subarch = sous-catégorie de cette même architecture.         *
+*                ins     = désignation première de l'instruction manipulée.   *
+*                sep     = caractère de séparation avant les détails.         *
+*                details = particularités de l'instruction.                   *
+*                pp      = pré-processeur pour les échanges de chaînes.       *
+*                prefix  = préfixe pour le type de définitions d'opérandes.   *
+*                                                                             *
+*  Description : Traduit en code une sous-fonction de désassemblage.          *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+bool write_encoding_spec_format_disass(const encoding_spec *spec, int fd, const char *arch, const char *subarch, const char *ins, char sep, const char *details, const pre_processor *pp, const char *prefix)
+{
+    bool result;                            /* Bilan à retourner           */
+    bool quick_exit;                        /* Inclusion de sortie rapide ?*/
+    bool bad_exit;                          /* Ajout d'une sortie d'échec ?*/
+    const char *new_ins;                    /* Nouvelle définition de nom  */
+
+    result = true;
+
+    /* Déclarations préalables */
+
+    dprintf(fd, "\tGArchInstruction *result;               /* Instruction créée à renvoyer*/\n");
+    dprintf(fd, "\tSourceEndian endian;                    /* Boutisme lié au binaire     */\n");
+
+    dprintf(fd, "\n");
+
+    /* Création de l'instruction en elle-même */
+
+    new_ins = get_new_keyword_from_syntax_items(spec->syntax);
+
+    if (new_ins != NULL)
+        dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, new_ins);
+    else
+    {
+        if (sep == '\0')
+            dprintf(fd, "\tresult = g_%s_instruction_new(\"%s\");\n", arch, ins);
+        else
+            dprintf(fd, "\tresult = g_%s_instruction_new(\"%s%c%s\");\n", arch, ins, sep, details);
+    }
+
+    dprintf(fd, "\n");
+
+    /* Inscriptions des éventuelles fonctions ou propriété à lier */
+
+    result &= write_hook_functions(spec->hooks, fd);
+
+    result &= write_decoding_rules(spec->rules, CAT_CHECKED_CALL,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit);
+
+    result &= write_decoding_rules(spec->rules, CAT_CALL,
+                                   fd, arch, subarch, spec->bits, spec->conversions, pp, &quick_exit);
+
+    /* Création des opérandes */
+
+    dprintf(fd, "\tendian = g_arch_processor_get_endianness(G_ARCH_PROCESSOR(proc));\n");
+
+    dprintf(fd, "\n");
+
+    bad_exit = false;
+
+    result &= define_operands_loading(spec->format, fd, arch, prefix, &bad_exit);
+
+    /* Conclusion de la procédure */
+
+    dprintf(fd, "\treturn result;\n");
+
+    dprintf(fd, "\n");
+
+    if (bad_exit)
+    {
+        dprintf(fd, " bad_exit:\n");
+        dprintf(fd, "\n");
+
+        dprintf(fd, "\tg_object_unref(G_OBJECT(result));\n");
+        dprintf(fd, "\treturn NULL;\n");
+
+        dprintf(fd, "\n");
+
+    }
+
+    return result;
+
+}
diff --git a/tools/d2c/spec.h b/tools/d2c/spec.h
index e09aa49..8c62fc3 100644
--- a/tools/d2c/spec.h
+++ b/tools/d2c/spec.h
@@ -31,6 +31,7 @@
 #include "pproc.h"
 #include "bits/manager.h"
 #include "conv/manager.h"
+#include "format/manager.h"
 #include "hooks/manager.h"
 #include "rules/manager.h"
 #include "syntax/manager.h"
@@ -53,6 +54,9 @@ void define_encoding_spec_code_name(encoding_spec *, char *, unsigned int);
 /* Indique si une spécification se range dans une catégorie. */
 bool has_encoding_spec_prefix(const encoding_spec *, const char *);
 
+/* Fournit le gestionnaire des définitions d'opérandes. */
+operands_format *get_format_in_encoding_spec(const encoding_spec *);
+
 /* Fournit le gestionnaire des bits d'un encodage d'instruction. */
 coding_bits *get_bits_in_encoding_spec(const encoding_spec *);
 
@@ -71,6 +75,9 @@ decoding_rules *get_rules_in_encoding_spec(const encoding_spec *);
 /* Traduit en code une sous-fonction de désassemblage. */
 bool write_encoding_spec_disass(const encoding_spec *, int, const char *, const char *, const char *, const char *, unsigned int, const pre_processor *);
 
+/* Traduit en code une sous-fonction de désassemblage. */
+bool write_encoding_spec_format_disass(const encoding_spec *, int, const char *, const char *, const char *, char, const char *, const pre_processor *, const char *);
+
 
 
 #endif  /* _TOOLS_D2C_SPEC_H */
diff --git a/tools/d2c/tokens.l b/tools/d2c/tokens.l
index e48d079..1e4b7b0 100644
--- a/tools/d2c/tokens.l
+++ b/tools/d2c/tokens.l
@@ -6,41 +6,19 @@
 }
 
 
-
 %{
 
-    //typedef struct _rented_coder rented_coder;
-
-
-//#include "d2c-d2c_gram.h"
-
-#include <ctype.h>
-#include <string.h>
-
-
 #include "manual.h"
 
-
-
 %}
 
+
 %option noyywrap
 %option nounput
- //%option noinput
 %option yylineno
 %option stack
 %option noyy_top_state
 
- //%option reentrant
- //%option bison-bridge
-
-/* %option bison-bridge */
-/* %option bison-locations */
-/* %option ecs */
-/* %option nodefault */
-/* %option noyywrap */
-/* %option reentrant */
-
 
 %x comments
 
@@ -52,81 +30,65 @@
 %x raw_line
 
 
-
 %%
 
 
-[ \t\n]+                            { }
-
-"/*"                                { BEGIN(comments); }
-<comments>"*/"                      { BEGIN(INITIAL); }
-<comments>[^*\n]                    { }
-<comments>"Copyright"[^\n]*         { yylvalp->string = strdup(yytext); return COPYRIGHT; }
-<comments>"*"                       { }
-<comments>"\n"                      { }
-
-
-"@title"                            { BEGIN(ins_name); return TITLE; }
-
-<ins_name>[ ][A-Za-z-]+             { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
-<try_details>[ ,/]                  { BEGIN(ins_details); }
-<try_details>[\n]                   { BEGIN(INITIAL); }
-
-<ins_details>[^\n]*                 { yylvalp->cstring = yytext; return INS_DETAILS; }
-<ins_details>[\n]                   { BEGIN(INITIAL); }
-
-
-
-"@encoding"                         { BEGIN(encoding); return ENCODING; }
-
-<encoding>[ ]                       { }
-<encoding>"("                       { BEGIN(encoding_type); }
-
-<encoding_type>[A-Za-z]             { yylvalp->string = strdup(yytext); return TYPE; }
-<encoding_type>[0-9]+               { yylvalp->integer = atoi(yytext); return NUMBER; }
-<encoding_type>")"                  { BEGIN(encoding); }
-
-<encoding>"{"                       { BEGIN(encoding_content); }
-<encoding_content>[ \t\n]+          { }
-<encoding_content>"}"               { BEGIN(INITIAL); }
-
-
-
-<encoding_content>"@half "          { yy_push_state(raw_line); return HALF; }
-<encoding_content>"@word "          { yy_push_state(raw_line); return WORD; }
-
-
-<raw_line>[^\n]+                    { yylvalp->cstring = yytext; return RAW_LINE; }
-<raw_line>"\n"                      { yy_pop_state(); }
+[ \t\n]+                        { }
 
+"/*"                            { BEGIN(comments); }
+<comments>"*/"                  { BEGIN(INITIAL); }
+<comments>[^*\n]                { }
+<comments>"Copyright"[^\n]*     { yylvalp->string = strdup(yytext); return COPYRIGHT; }
+<comments>"*"                   { }
+<comments>"\n"                  { }
 
 
+"@title"                        { BEGIN(ins_name); return TITLE; }
 
-<encoding_content>"@syntax "        { yy_push_state(raw_line); return SYNTAX; }
+<ins_name>[ ][A-Za-z-]+         { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
+<try_details>[ ,/-]             { BEGIN(ins_details); yylvalp->character = yytext[0]; return INS_SEP; }
+<try_details>[\n]               { BEGIN(INITIAL); }
 
+<ins_details>[^\n]*             { yylvalp->cstring = yytext; return INS_DETAILS; }
+<ins_details>[\n]               { BEGIN(INITIAL); }
 
 
 
+"@encoding"                     { BEGIN(encoding); return ENCODING; }
 
-<encoding_content>"@conv"           { return CONV; }
+<encoding>[ ]                   { }
+<encoding>"("                   { BEGIN(encoding_type); }
 
+<encoding_type>[A-Za-z]         { yylvalp->string = strdup(yytext); return TYPE; }
+<encoding_type>[0-9]+           { yylvalp->integer = atoi(yytext); return NUMBER; }
+<encoding_type>")"              { BEGIN(encoding); }
 
+<encoding>"{"                   { BEGIN(encoding_content); }
+<encoding_content>[ \t\n]+      { }
+<encoding_content>"}"           { BEGIN(INITIAL); }
 
 
-<encoding_content>"{" {
-    read_block(temp);
-    yylvalp->cstring = temp; return RAW_BLOCK;
- }
+<encoding_content>"@format"     { yy_push_state(raw_line); return FORMAT; }
 
+<encoding_content>"@half"       { yy_push_state(raw_line); return HALF; }
+<encoding_content>"@word"       { yy_push_state(raw_line); return WORD; }
 
+<encoding_content>"@syntax"     { yy_push_state(raw_line); return SYNTAX; }
 
+<encoding_content>"@conv"       { return CONV; }
 
+<encoding_content>"@hooks"      { return HOOKS; }
 
+<encoding_content>"@rules"      { return RULES; }
 
 
-<encoding_content>"@hooks"          { return HOOKS; }
+<raw_line>[^\n]+                { yylvalp->cstring = yytext; return RAW_LINE; }
+<raw_line>"\n"                  { yy_pop_state(); }
 
-<encoding_content>"@rules"          { return RULES; }
+<encoding_content>"{"           {
+                                    read_block(temp);
+                                    yylvalp->cstring = temp; return RAW_BLOCK;
+                                }
 
 
 %%
-- 
cgit v0.11.2-87-g4458