summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog48
-rw-r--r--src/arch/arm/v7/arm.c121
-rw-r--r--src/arch/arm/v7/helpers.c56
-rw-r--r--src/arch/arm/v7/helpers.h4
-rw-r--r--src/arch/arm/v7/opcodes/Makefile.am1
-rw-r--r--src/arch/arm/v7/opdefs/Makefile.am4
-rw-r--r--src/arch/arm/v7/opdefs/bl_A8825.d84
-rwxr-xr-xsrc/common/Makefile.am1
-rw-r--r--src/common/asm.c67
-rw-r--r--src/common/asm.h38
-rw-r--r--tools/Makefile.am13
-rw-r--r--tools/bits.c363
-rw-r--r--tools/bits.h87
-rw-r--r--tools/coder.c1306
-rw-r--r--tools/coder.h53
-rw-r--r--tools/conv.c1640
-rw-r--r--tools/conv.h160
-rw-r--r--tools/d2c_gram.y133
-rw-r--r--tools/d2c_tok.l36
-rw-r--r--tools/helpers.c144
-rw-r--r--tools/helpers.h47
-rw-r--r--tools/macros.c167
-rw-r--r--tools/macros.h30
-rw-r--r--tools/pproc.c214
-rw-r--r--tools/pproc.h67
-rw-r--r--tools/rules.c439
-rw-r--r--tools/rules.h91
-rw-r--r--tools/spec.c349
-rw-r--r--tools/spec.h72
-rw-r--r--tools/syntax.c321
-rw-r--r--tools/syntax.h61
31 files changed, 4884 insertions, 1333 deletions
diff --git a/ChangeLog b/ChangeLog
index d322429..2310c44 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,51 @@
+14-11-14 Cyrille Bagard <nocbos@gmail.com>
+
+ * src/arch/arm/v7/arm.c:
+ Support one more instructions category (§ A5.5).
+
+ * src/arch/arm/v7/helpers.c:
+ * src/arch/arm/v7/helpers.h:
+ Load sign extended operands from raw values.
+
+ * src/arch/arm/v7/opcodes/Makefile.am:
+ Add the 'bl.d' file to libarcharmv7opcodes_la_SOURCES.
+
+ * src/arch/arm/v7/opdefs/bl_A8825.d:
+ New entries: define basic definition for bl/blx instructions.
+
+ * src/arch/arm/v7/opdefs/Makefile.am:
+ Add a new macro 'SignExtend' to D2C_MACROS and bl_A8825.d to ARMV7_DEFS.
+
+ * src/common/asm.c:
+ * src/common/asm.h:
+ New entries: compute the position of the first bit set in a 32b word.
+
+ * src/common/Makefile.am:
+ Add the 'asm.[ch]' files to libcommon_la_SOURCES.
+
+ * tools/bits.c:
+ * tools/bits.h:
+ * tools/coder.c:
+ * tools/coder.h:
+ * tools/conv.c:
+ * tools/conv.h:
+ * tools/d2c_gram.y:
+ * tools/d2c_tok.l:
+ * tools/helpers.c:
+ * tools/helpers.h:
+ * tools/macros.c:
+ * tools/macros.h:
+ * tools/Makefile.am:
+ * tools/pproc.c:
+ * tools/pproc.h:
+ * tools/rules.c:
+ * tools/rules.h:
+ * tools/spec.c:
+ * tools/spec.h:
+ * tools/syntax.c:
+ * tools/syntax.h:
+ Rewrite and extend the whole code for the instructions definitions compiler.
+
14-11-01 Cyrille Bagard <nocbos@gmail.com>
* src/arch/instruction.c:
diff --git a/src/arch/arm/v7/arm.c b/src/arch/arm/v7/arm.c
index 5295ef8..b7d4ff1 100644
--- a/src/arch/arm/v7/arm.c
+++ b/src/arch/arm/v7/arm.c
@@ -39,6 +39,8 @@ static GArchInstruction *process_armv7_data_processing_and_miscellaneous_instruc
/* Désassemble une instruction ARMv7 de données de registre. */
static GArchInstruction *process_armv7_data_processing_register(uint32_t);
+/* Désassemble une instruction ARMv7 de données ou autre. */
+static GArchInstruction *process_armv7_branch_branch_with_link_and_block_data_transfer(uint32_t);
@@ -47,7 +49,7 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);
#define process_armv7_load_store_word_and_unsigned_byte(raw) NULL
#define process_armv7_load_store_word_and_unsigned_byte(raw) NULL
#define process_armv7_media_instructions(raw) NULL
-#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL
+//#define process_armv7_branch_branch_with_link_and_block_data_transfer(raw) NULL
#define process_armv7_coprocessor_instructions_and_Supervisor_call(raw) NULL
#define process_armv7_unconditional_instructions(raw) NULL
@@ -93,6 +95,26 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t);
#define armv7_read_instr_mvn_register(raw) NULL
+// process_armv7_branch_branch_with_link_and_block_data_transfer
+
+#define armv7_read_instr_stmda_stmed(raw) NULL
+#define armv7_read_instr_ldmda_ldmfa(raw) NULL
+#define armv7_read_instr_stm_stmia_stmea(raw) NULL
+#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL
+#define armv7_read_instr_ldm_ldmia_ldmfd_arm(raw) NULL
+#define armv7_read_instr_pop_arm(raw) NULL
+#define armv7_read_instr_stmdb_stmfd(raw) NULL
+#define armv7_read_instr_stmdb_stmfd(raw) NULL
+#define armv7_read_instr_push(raw) NULL
+#define armv7_read_instr_ldmdb_ldmea(raw) NULL
+#define armv7_read_instr_stmib_stmfa(raw) NULL
+#define armv7_read_instr_ldmib_ldmed(raw) NULL
+#define armv7_read_instr_stm_user_registers(raw) NULL
+#define armv7_read_instr_ldm_user_registers(raw) NULL
+#define armv7_read_instr_ldm_exception_return(raw) NULL
+#define armv7_read_instr_b(raw) NULL
+//#define armv7_read_instr_bl_blx_immediate(raw) NULL
+
@@ -127,7 +149,6 @@ GArchInstruction *process_armv7_instruction_set_encoding(uint32_t raw)
op1 = (raw >> 25) & 0x7;
op = (raw >> 4) & 0x1;
-
if (cond != b1111)
{
if ((op1 & b110) == b000)
@@ -403,3 +424,99 @@ static GArchInstruction *process_armv7_data_processing_register(uint32_t raw)
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = donnée brute de 32 bits à désassembler. *
+* *
+* Description : Désassemble une instruction ARMv7 de données ou autre. *
+* *
+* Retour : Instruction mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GArchInstruction *process_armv7_branch_branch_with_link_and_block_data_transfer(uint32_t raw)
+{
+ GArchInstruction *result; /* Instruction à retourner */
+ uint32_t op; /* Champ 'op' à retrouver */
+ uint32_t rn; /* Champ 'rn' à retrouver */
+ uint32_t r; /* Champ 'r' à retrouver */
+
+ /**
+ * Suit les directives de :
+ * § A5.5 Branch, branch with link, and block data transferr
+ */
+
+ result = NULL;
+
+ op = (raw >> 20) & 0x3f;
+ rn = (raw >> 16) & 0xf;
+ r = (raw >> 15) & 0x1;
+
+ if ((op & b111101) == b000000)
+ result = armv7_read_instr_stmda_stmed(raw);
+
+ else if ((op & b111101) == b000001)
+ result = armv7_read_instr_ldmda_ldmfa(raw);
+
+ else if ((op & b111101) == b001000)
+ result = armv7_read_instr_stm_stmia_stmea(raw);
+
+ else if (op == b001001)
+ result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw);
+
+ else if (op == b001011)
+ {
+ if (rn != b1101)
+ result = armv7_read_instr_ldm_ldmia_ldmfd_arm(raw);
+ else /* if (rn == b1101) */
+ result = armv7_read_instr_pop_arm(raw);
+ }
+
+ else if (op == b010000)
+ result = armv7_read_instr_stmdb_stmfd(raw);
+
+ else if (op == b010010)
+ {
+ if (rn != b1101)
+ result = armv7_read_instr_stmdb_stmfd(raw);
+ else /* if (rn == b1101) */
+ result = armv7_read_instr_push(raw);
+ }
+
+ else if ((op & b111101) == b010001)
+ result = armv7_read_instr_ldmdb_ldmea(raw);
+
+ else if ((op & b111101) == b011000)
+ result = armv7_read_instr_stmib_stmfa(raw);
+
+ else if ((op & b111101) == b011001)
+ result = armv7_read_instr_ldmib_ldmed(raw);
+
+ else if ((op & b100101) == b000100)
+ result = armv7_read_instr_stm_user_registers(raw);
+
+ else if ((op & b100101) == b000101)
+ {
+ if (r == b0)
+ result = armv7_read_instr_ldm_user_registers(raw);
+ else /* if (r == b1) */
+ result = armv7_read_instr_ldm_exception_return(raw);
+ }
+
+ else if ((op & b110000) == b100000)
+ result = armv7_read_instr_b(raw);
+
+ else if ((op & b110000) == b110000)
+ result = armv7_read_instr_bl_blx_immediate(raw);
+
+ return result;
+
+}
diff --git a/src/arch/arm/v7/helpers.c b/src/arch/arm/v7/helpers.c
index 632c1b7..e7c9ad8 100644
--- a/src/arch/arm/v7/helpers.c
+++ b/src/arch/arm/v7/helpers.c
@@ -26,11 +26,67 @@
#include "register.h"
#include "../../register.h"
+#include "../../immediate.h"
+#include "../../../common/asm.h"
/******************************************************************************
* *
+* Paramètres : value = valeur sur 32 bits maximum à traiter. *
+* topbit = valeur du bit de poids fort manipulé. *
+* size = taille de la valeur finale à constituer. *
+* *
+* Description : Crée un opérande de valeur immédiate avec extension de signe.*
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GArchOperand *sign_extend_armv7_imm(uint32_t value, bool topbit, unsigned int size)
+{
+ GArchOperand *result; /* Opérande à faire remonter */
+ unsigned int msb; /* Position du premier bit à 1 */
+ MemoryDataSize mds; /* Conversion de la taille */
+ uint32_t val4; /* Valeur sur 4 bits */
+ uint32_t val8; /* Valeur sur 8 bits */
+ uint32_t val16; /* Valeur sur 16 bits */
+ uint32_t val32; /* Valeur sur 32 bits */
+ unsigned int i; /* Boucle de parcours */
+
+ result = NULL;
+
+ topbit &= msb_32(value, &msb);
+
+ switch (size)
+ {
+
+#define SIGN_EXTEND_CASE(sz) \
+ case sz: \
+ mds = MDS_ ## sz ## _BITS_SIGNED; \
+ val ## sz = value; \
+ if (topbit) \
+ for (i = msb + 1; i < sz; i++) \
+ val ## sz |= (1 << i); \
+ result = g_imm_operand_new_from_value(mds, val ## sz); \
+ break;
+
+ SIGN_EXTEND_CASE(4);
+ SIGN_EXTEND_CASE(8);
+ SIGN_EXTEND_CASE(16);
+ SIGN_EXTEND_CASE(32);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : index = indice du registre correspondant. *
* *
* Description : Crée un opérande représentant un registre ARMv7. *
diff --git a/src/arch/arm/v7/helpers.h b/src/arch/arm/v7/helpers.h
index 9ea0d74..087b2e7 100644
--- a/src/arch/arm/v7/helpers.h
+++ b/src/arch/arm/v7/helpers.h
@@ -25,6 +25,7 @@
#define _ARCH_ARM_V7_HELPERS_H
+#include <stdbool.h>
#include <stdint.h>
@@ -32,6 +33,9 @@
+/* Crée un opérande de valeur immédiate avec extension de signe. */
+GArchOperand *sign_extend_armv7_imm(uint32_t, bool, unsigned int);
+
/* Crée un opérande représentant un registre ARMv7. */
GArchOperand *translate_armv7_register(uint8_t);
diff --git a/src/arch/arm/v7/opcodes/Makefile.am b/src/arch/arm/v7/opcodes/Makefile.am
index e77b7e8..dc5c8d9 100644
--- a/src/arch/arm/v7/opcodes/Makefile.am
+++ b/src/arch/arm/v7/opcodes/Makefile.am
@@ -2,6 +2,7 @@
noinst_LTLIBRARIES = libarcharmv7opcodes.la
libarcharmv7opcodes_la_SOURCES = \
+ bl.c \
mov.c \
subs.c
diff --git a/src/arch/arm/v7/opdefs/Makefile.am b/src/arch/arm/v7/opdefs/Makefile.am
index f2c5a35..9aa6a82 100644
--- a/src/arch/arm/v7/opdefs/Makefile.am
+++ b/src/arch/arm/v7/opdefs/Makefile.am
@@ -17,9 +17,11 @@ D2C_MACROS = \
-M SetFlags=g_armv7_instruction_define_setflags \
-M Condition=g_arm_instruction_set_cond \
-M Register=translate_armv7_register \
- -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, "
+ -M "ExpandImmC32=g_imm_operand_new_from_value(MDS_32_BITS_UNSIGNED, " \
+ -M SignExtend=sign_extend_armv7_imm
ARMV7_DEFS = \
+ bl_A8825.d \
mov_A88104.d \
subs_B9320.d
diff --git a/src/arch/arm/v7/opdefs/bl_A8825.d b/src/arch/arm/v7/opdefs/bl_A8825.d
new file mode 100644
index 0000000..c9ef5d0
--- /dev/null
+++ b/src/arch/arm/v7/opdefs/bl_A8825.d
@@ -0,0 +1,84 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * ##FILE## - traduction d'instructions ARMv7
+ *
+ * Copyright (C) 2014 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide 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.
+ *
+ * Chrysalide 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/>.
+ */
+
+
+@title BL, BLX (immediate)
+
+@encoding(T1) {
+
+ @word 1 1 1 1 0 S(1) imm10H(10) 1 1 J1(1) 1 J2(1) imm10L(10) H(1)
+
+ @syntax <imm32>
+
+ @conv {
+
+ I1 = NOT(J1 EOR S)
+ I2 = NOT(J2 EOR S)
+ imm32 = SignExtend(S:I1:I2:imm10H:imm10L:'00', s, 32)
+
+ }
+
+}
+
+@encoding(T2) {
+
+ @word 1 1 1 1 0 S(1) imm10(10) 1 1 J1(1) 0 J2(1) imm11(11)
+
+ @syntax <imm32>
+
+ @conv {
+
+ I1 = NOT(J1 EOR S)
+ I2 = NOT(J2 EOR S)
+ imm32 = SignExtend(S:I1:I2:imm10:imm11:'0', S, 32)
+
+ }
+
+}
+
+@encoding(A1) {
+
+ @word cond(4) 1 0 1 1 imm24(24)
+
+ @syntax <imm32>
+
+ @conv {
+
+ imm32 = SignExtend(imm24:'00', 0, 32)
+
+ }
+
+}
+
+@encoding(A2) {
+
+ @word cond(4) 1 0 1 H(1) imm24(24)
+
+ @syntax <imm32>
+
+ @conv {
+
+ imm32 = SignExtend(imm24:H:'0', 0, 32)
+
+ }
+
+}
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 198de32..7615f43 100755
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -2,6 +2,7 @@
lib_LTLIBRARIES = libcommon.la
libcommon_la_SOURCES = \
+ asm.h asm.c \
bconst.h \
cpp.h \
dllist.h dllist.c \
diff --git a/src/common/asm.c b/src/common/asm.c
new file mode 100644
index 0000000..597013a
--- /dev/null
+++ b/src/common/asm.c
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * asm.c - implémentations génériques de fonctionnalités spécifiques
+ *
+ * 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 "asm.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : v = valeur quelconque sur 32 bits. *
+* p = position du premier bit à 1 (poids fort). [OUT] *
+* *
+* Description : Détermine l'indice du premier bit à 1, côté gauche. *
+* *
+* Retour : true si le nombre est différent de zéro, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool msb_32(uint32_t v, unsigned int *p)
+{
+ static const unsigned int bval[] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4 };
+
+ /* S'il n'y a aucun bit à 1... */
+ if (v == 0) return false;
+
+ /**
+ * Il existe de nombreuses méthodes pour obtenir le résultat attendu
+ * sans recourir à des extensions GCC ou à des instructions d'assembleur :
+ *
+ * - http://stackoverflow.com/questions/2589096/find-most-significant-bit-left-most-that-is-set-in-a-bit-array
+ * - http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
+ *
+ */
+
+ *p = 0;
+
+ if (v & 0xffff0000) { *p += 16 / 1; v >>= 16 / 1; }
+ if (v & 0x0000ff00) { *p += 16 / 2; v >>= 16 / 2; }
+ if (v & 0x000000f0) { *p += 16 / 4; v >>= 16 / 4; }
+
+ *p += bval[v];
+
+ return true;
+
+}
diff --git a/src/common/asm.h b/src/common/asm.h
new file mode 100644
index 0000000..047d8db
--- /dev/null
+++ b/src/common/asm.h
@@ -0,0 +1,38 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * asm.h - prototypes pour les implémentations génériques de fonctionnalités spécifiques
+ *
+ * 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 _COMMON_ASM_H
+#define _COMMON_ASM_H
+
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+
+/* Détermine l'indice du premier bit à 1, côté gauche. */
+bool msb_32(uint32_t, unsigned int *);
+
+
+
+#endif /* _COMMON_ASM_H */
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 9a91f9d..d0fdbe8 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -7,13 +7,20 @@ bin_PROGRAMS = d2c
d2c_SOURCES = \
+ bits.h bits.c \
coder.h coder.c \
+ conv.h conv.c \
+ d2c_tok.l \
d2c_gram.y \
- d2c_tok.l
+ helpers.h helpers.c \
+ pproc.h pproc.c \
+ rules.h rules.c \
+ spec.h spec.c \
+ syntax.h syntax.c
-d2c_YFLAGS = -d -p d2c_ -o y.tab.c
+d2c_YFLAGS = -v -d -p d2c_ -o y.tab.c
-d2c_LFLAGS = -P d2c_ -o lex.yy.c
+d2c_LFLAGS = -P d2c_ --header-file=d2c_tok.h -o lex.yy.c
AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
diff --git a/tools/bits.c b/tools/bits.c
new file mode 100644
index 0000000..32c3fd9
--- /dev/null
+++ b/tools/bits.c
@@ -0,0 +1,363 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.c - compréhension et manipulation des champs de bits
+ *
+ * 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 "bits.h"
+
+
+#include <assert.h>
+#include <inttypes.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#include "helpers.h"
+
+
+
+
+
+/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */
+
+
+/* Elément d'un mot décodé */
+struct _raw_bitfield
+{
+ char *name; /* Désignation humaine */
+ unsigned int start; /* Position de départ */
+ unsigned int length; /* Taille du champ */
+
+ bool used; /* Champ défini & utilisé */
+
+};
+
+
+
+
+/* Représentation de l'ensemble des bits de codage */
+struct _coding_bits
+{
+ raw_bitfield *fields; /* Champs de bits détectés */
+ size_t bf_count; /* Nombre de ces champs */
+ uint64_t bits; /* Bits invariables */
+ uint64_t mask; /* Emplacement de ces bits */
+ unsigned int curpos; /* Position pendant l'analyse */
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à consulter. *
+* *
+* Description : Indique le nombre de bits utilisés par le champ. *
+* *
+* Retour : Nombre de bits considérés. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+unsigned int get_raw_bitfield_length(const raw_bitfield *field)
+{
+ return field->length;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : field = champ de bits à traiter. *
+* *
+* Description : Marque un champ de bits comme étant utile. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void mark_raw_bitfield_as_used(raw_bitfield *field)
+{
+ field->used = true;
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau gestionnaire des bits d'encodage brut. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+coding_bits *create_coding_bits(void)
+{
+ coding_bits *result; /* Définition vierge à renvoyer*/
+
+ result = (coding_bits *)calloc(1, sizeof(coding_bits));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire d'un ensemble de bits à libérer. *
+* *
+* Description : Supprime de la mémoire un gestionnaire de bits d'encodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_coding_bits(coding_bits *bits)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < bits->bf_count; i++)
+ free(bits->fields[i].name);
+
+ if (bits->fields != NULL)
+ free(bits->fields);
+
+ free(bits);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. *
+* name = désignation humaine du champ remarqué. *
+* length = taille du champ à mémoriser. *
+* *
+* Description : Note la présence d'un champ remarquable dans une définition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_named_field_in_bits(coding_bits *bits, char *name, unsigned int length)
+{
+ raw_bitfield *field; /* Nouveau champ à constituer */
+
+ assert((bits->curpos + length) < 64);
+
+ bits->fields = (raw_bitfield *)realloc(bits->fields,
+ ++bits->bf_count * sizeof(raw_bitfield));
+
+ field = &bits->fields[bits->bf_count - 1];
+
+ field->name = make_string_lower(name);
+ field->start = bits->curpos;
+ field->length = length;
+
+ bits->curpos += length;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. *
+* val = valeur du bit à prendre en compte. *
+* *
+* Description : Note la présence d'un bit invariable dans une définition. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_bit_in_bits(coding_bits *bits, int val)
+{
+ assert(bits->curpos < 64);
+
+ bits->bits |= (val ? 1 : 0) << bits->curpos;
+ bits->mask |= 1 << bits->curpos;
+
+ bits->curpos++;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire de bits d'encodage brut à consulter. *
+* *
+* Description : Indique le nombre de bits traités. *
+* *
+* Retour : Quantité, positive ou nulle. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+unsigned int count_coded_bits(const coding_bits *bits)
+{
+ return bits->curpos;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire d'encodage brut à consulter. *
+* name = désignation humaine du champ à retrouver. *
+* *
+* Description : Recherche un champ donné dans un ensemble de champs de bits. *
+* *
+* Retour : Structure associée au champ trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+raw_bitfield *find_named_field_in_bits(const coding_bits *bits, const char *name)
+{
+ raw_bitfield *result; /* Champ de bits à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < bits->bf_count && result == NULL; i++)
+ if (strcmp(bits->fields[i].name, name) == 0)
+ result = &bits->fields[i];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool declare_used_bits_fields(const coding_bits *bits, int fd, unsigned int wide)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < bits->bf_count; i++)
+ if (bits->fields[i].used)
+ dprintf(fd, "\t\tuint%u_t raw_%s;\n", wide, bits->fields[i].name);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool check_bits_correctness(const coding_bits *bits, int fd)
+{
+ dprintf(fd, "\t\tif ((raw & 0x%" PRIx64 ") != 0x%" PRIx64 ") return NULL;\n", bits->mask, bits->bits);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_used_bits_fields(const coding_bits *bits, int fd)
+{
+ size_t i; /* Boucle de parcours */
+ raw_bitfield *rf; /* Accès confortable à un champ*/
+
+ for (i = 0; i < bits->bf_count; i++)
+ {
+ rf = &bits->fields[i];
+ if (!rf->used) continue;
+
+ dprintf(fd, "\t\traw_%s = (_raw >> %u) & 0x%llx;\n", rf->name, rf->start, (1ull << rf->length) - 1);
+
+ }
+
+ return true;
+
+}
diff --git a/tools/bits.h b/tools/bits.h
new file mode 100644
index 0000000..aa4b7aa
--- /dev/null
+++ b/tools/bits.h
@@ -0,0 +1,87 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * bits.h - prototypes pour la compréhension et la manipulation des champs de bits
+ *
+ * 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_BITS_H
+#define _TOOLS_BITS_H
+
+
+#include <stdbool.h>
+
+
+
+
+/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */
+
+
+/* Elément d'un mot décodé */
+typedef struct _raw_bitfield raw_bitfield;
+
+
+
+/* Indique le nombre de bits utilisés par le champ. */
+unsigned int get_raw_bitfield_length(const raw_bitfield *);
+
+/* Marque un champ de bits comme étant utile. */
+void mark_raw_bitfield_as_used(raw_bitfield *);
+
+
+
+
+
+/* Représentation de l'ensemble des bits de codage */
+typedef struct _coding_bits coding_bits;
+
+
+
+/* Crée un nouveau gestionnaire des bits d'encodage brut. */
+coding_bits *create_coding_bits(void);
+
+/* Supprime de la mémoire un gestionnaire de bits d'encodage. */
+void delete_coding_bits(coding_bits *);
+
+
+
+/* Note la présence d'un champ remarquable dans une définition. */
+void register_named_field_in_bits(coding_bits *, char *, unsigned int);
+
+/* Note la présence d'un bit invariable dans une définition. */
+void register_bit_in_bits(coding_bits *, int);
+
+/* Indique le nombre de bits traités. */
+unsigned int count_coded_bits(const coding_bits *);
+
+/* Recherche un champ donné dans un ensemble de champs de bits. */
+raw_bitfield *find_named_field_in_bits(const coding_bits *, const char *);
+
+/* Déclare les variables C associées aux champs de bits. */
+bool declare_used_bits_fields(const coding_bits *, int, unsigned int);
+
+/* Vérifie que les bits fixes correspondent au masque attendu. */
+bool check_bits_correctness(const coding_bits *, int);
+
+/* Définit les variables C associées aux champs de bits. */
+bool define_used_bits_fields(const coding_bits *, int);
+
+
+
+#endif /* _TOOLS_BITS_H */
diff --git a/tools/coder.c b/tools/coder.c
index 3606bea..5856d80 100644
--- a/tools/coder.c
+++ b/tools/coder.c
@@ -25,32 +25,23 @@
#include <assert.h>
-#include <ctype.h>
#include <fcntl.h>
-#include <inttypes.h>
#include <malloc.h>
#include <regex.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <sys/param.h>
+#include "helpers.h"
-/* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */
-/* Conversion des chaînes en chaînes */
-typedef struct _string_exch
-{
- const char *src; /* Chaîne à trouver */
- const char *dest; /* Chaîne de remplacement */
+/* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */
-} string_exch;
-struct _encoding_spec;
/* Suivi des constructions */
@@ -60,89 +51,24 @@ struct _rented_coder
const char *arch; /* Architecture à traiter */
const char *header; /* En-tête pour les en-têtes */
- string_exch *macros; /* Remplacements de chaînes */
- size_t macros_count; /* Nombre de ces remplacements */
-
- string_exch *encodings; /* Traductions d'encodages */
- size_t encodings_count; /* Nombre de ces traductions */
+ pre_processor *pp; /* Pré-processeur avec macros */
char *copyright; /* Récupération des droits */
char *ins; /* Désignation humaine */
char *details; /* Eventuels compléments */
- struct _encoding_spec *specs; /* Définitions déjà en place */
+ encoding_spec **specs; /* Définitions déjà en place */
size_t specs_count; /* Nombre de ces définitions */
- struct _encoding_spec *cur_spec; /* Définition courante */
+ encoding_spec *cur_spec; /* Définition courante */
};
-/* Recherche l'existence d'une macro pour un remplacement. */
-static const char *find_macro_in_coder(const rented_coder *, const char *);
-
/* --------------------------- REPRESENTATION D'ENCODAGES --------------------------- */
-struct _dec_bitfield;
-struct _syntax_item;
-struct _conv_func;
-struct _extra_rule;
-
-
-/* Mémorisation d'un encodage complet */
-typedef struct _encoding_spec
-{
- char *prefix; /* Distinction principale */
- unsigned int index; /* Distinction secondaire */
-
- struct _dec_bitfield *bitfields; /* Champs de bits détectés */
- size_t bf_count; /* Nombre de ces champs */
- uint64_t bits; /* Bits invariables */
- uint64_t mask; /* Emplacement de ces bits */
- unsigned int curpos; /* Position pendant l'analyse */
-
- struct _syntax_item *items; /* Eléments de la syntaxe */
- size_t items_count; /* Nombre de ces éléments */
-
- struct _conv_func *conversions; /* Conversions des données */
- size_t conv_count; /* Nombre de ces conversions */
-
- struct _extra_rule *rules; /* Régles supplémentaires */
- size_t rules_count; /* Nombre de ces règles */
-
-} encoding_spec;
-
-
-/* Libère de la mémoire une spécification d'encodage. */
-static void free_encoding_spec(encoding_spec *);
-
-
-
-/* ---------------------------- SYNTAXE DES INSTRUCTIONS ---------------------------- */
-
-
-/* Propriétés particulières pour les opérandes */
-typedef enum _SyntaxItemFlags
-{
- SIF_NONE = (0 << 0), /* Aucune propriété */
- SIF_DECIMAL = (1 << 0) /* Affichage en décimal */
-
-} SyntaxItemFlags;
-
-/* Elément défini dans une syntaxe */
-typedef struct _syntax_item
-{
- char *name; /* Désignation humaine */
- bool internal; /* Enregistrement générique ? */
- SyntaxItemFlags flags; /* Propriétés supplémentaires */
-
-} syntax_item;
-
-
-/* Libère de la mémoire tous les éléments de syntaxe. */
-static void free_all_syntax_items_in_spec(encoding_spec *);
@@ -161,11 +87,6 @@ typedef struct _dec_bitfield
-/* Recherche un champ donné dans une définition. */
-static const dec_bitfield *find_named_field_in_spec(const encoding_spec *, const char *);
-
-/* Libère de la mémoire toutes les champs de bits définis. */
-static void free_all_bitfields_in_spec(encoding_spec *);
@@ -182,67 +103,6 @@ typedef struct _conv_func
} conv_func;
-/* Libère de la mémoire toutes les conversions enregistrées. */
-static void free_all_conversion_in_spec(encoding_spec *);
-
-/* Recherche une fonction converrtissant une donnée brute. */
-static const conv_func *find_conversion_in_coder_spec(const encoding_spec *, const char *);
-
-
-
-/* --------------------------- CONDITIONS ET CONSEQUENCES --------------------------- */
-
-
-/* Expression d'une condition */
-struct _cond_expr
-{
- bool is_simple; /* Sélection de champ */
-
- union
- {
- struct
- {
- char *variable; /* Variable manipulée */
- CondCompType comp; /* Type de comparaison */
- char *bvalue; /* Valeur binaire comparée */
-
- } simple;
-
- struct
- {
- cond_expr *a; /* Première sous-expression */
- CondOpType operator; /* Relation entre expressions */
- cond_expr *b; /* Seconde sous-expression */
-
- } composed;
-
- };
-
-};
-
-/* Règles particulières */
-typedef struct _extra_rule
-{
- cond_expr *expr; /* Expression de déclenchement */
- CondActionType action; /* Conséquence d'une validation*/
- char *details; /* Eventuel complément d'info. */
-
-} extra_rule;
-
-
-/* Libère de la mémoire une expression conditionnelle. */
-static void free_cond_expr(cond_expr *);
-
-/* Traduit en code une expression de condition. */
-static bool write_cond_expr(const encoding_spec *, int, const cond_expr *);
-
-/* Libère de la mémoire des règles. */
-static void free_all_coder_spec_rules(encoding_spec *);
-
-/* Traduit en code les éventuelles règles présentes. */
-static bool write_coder_spec_rules(const rented_coder *, int, const encoding_spec *, bool *);
-
-
/* --------------------------- GENERATIONS DE CODE SOURCE --------------------------- */
@@ -253,23 +113,6 @@ 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);
-/* Traduit en code une sous-fonction de désassemblage. */
-static bool write_coder_spec_disass(const rented_coder *, int, const encoding_spec *, const char *, unsigned int);
-
-
-
-/* ---------------------------- MANIPULATIONS DE CHAINES ---------------------------- */
-
-
-/* Bascule toute une chaîne de caractères en (min|maj)uscules. */
-static char *_make_string_xxx(char *, int (* fn) (int));
-
-#define make_string_lower(str) _make_string_xxx(str, tolower)
-#define make_string_upper(str) _make_string_xxx(str, toupper)
-
-/* Traduit une chaîne en élément de fonction C. */
-static char *make_callable(const char *raw, bool);
-
/* ---------------------------------------------------------------------------------- */
@@ -295,7 +138,9 @@ rented_coder *create_coder(void)
result = (rented_coder *)calloc(1, sizeof(rented_coder));
- result->cur_spec = (encoding_spec *)calloc(1, sizeof(encoding_spec));
+ result->pp = create_pre_processor();
+
+ result->cur_spec = create_encoding_spec();
return result;
@@ -318,11 +163,7 @@ void delete_coder(rented_coder *coder)
{
size_t i; /* Boucle de parcours */
- if (coder->macros != NULL)
- free(coder->macros);
-
- if (coder->encodings != NULL)
- free(coder->encodings);
+ delete_pre_processor(coder->pp);
if (coder->ins != NULL)
free(coder->ins);
@@ -331,14 +172,12 @@ void delete_coder(rented_coder *coder)
free(coder->details);
for (i = 0; i < coder->specs_count; i++)
- free_encoding_spec(&coder->specs[i]);
+ delete_encoding_spec(coder->specs[i]);
if (coder->specs != NULL)
free(coder->specs);
- free_encoding_spec(coder->cur_spec);
-
- free(coder->cur_spec);
+ delete_encoding_spec(coder->cur_spec);
free(coder);
@@ -427,84 +266,18 @@ void set_coder_header_base(rented_coder *coder, const char *header)
/******************************************************************************
* *
* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* src = chaîne à remplacer dans les définitions. *
-* dest = chaîne de remplacement. *
* *
-* Description : Enregistre une correspondance en matière d'encodage. *
+* Description : Fournit le pré-processeur du compilateur. *
* *
-* Retour : - *
+* Retour : Pré-processeur à manipuler. *
* *
* Remarques : - *
* *
******************************************************************************/
-void register_encoding_in_coder(rented_coder *coder, const char *src, const char *dest)
+pre_processor *get_coder_pre_proc(const rented_coder *coder)
{
- string_exch *encoding; /* Traduction à conserver */
-
- coder->encodings = (string_exch *)realloc(coder->encodings, ++coder->encodings_count * sizeof(string_exch));
-
- encoding = &coder->encodings[coder->encodings_count - 1];
-
- encoding->src = src;
- encoding->dest = dest;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* src = chaîne à remplacer dans les définitions. *
-* dest = chaîne de remplacement. *
-* *
-* Description : Constitue la matière d'un système de macros. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void define_macro_for_coder(rented_coder *coder, const char *src, const char *dest)
-{
- string_exch *macro; /* Nouvelle macro à constituer */
-
- coder->macros = (string_exch *)realloc(coder->macros, ++coder->macros_count * sizeof(string_exch));
-
- macro = &coder->macros[coder->macros_count - 1];
-
- macro->src = src;
- macro->dest = dest;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* src = chaîne à remplacer dans les définitions. *
-* *
-* Description : Recherche l'existence d'une macro pour un remplacement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const char *find_macro_in_coder(const rented_coder *coder, const char *src)
-{
- const char *result; /* Trouvaille à renvoyer */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < coder->macros_count && result == NULL; i++)
- if (strcmp(coder->macros[i].src, src) == 0)
- result = coder->macros[i].dest;
-
- return result;
+ return coder->pp;
}
@@ -542,599 +315,29 @@ void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, const char
/******************************************************************************
* *
* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* prefix = distinction principale entre les définitions. *
-* index = distinction secondaire entre les définitions. *
-* *
-* Description : Enregistre une définition supplémentaire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index)
-{
- encoding_spec *spec; /* Définition à compléter */
-
- spec = coder->cur_spec;
-
- spec->prefix = prefix;
- spec->index = index;
-
- coder->specs = (encoding_spec *)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec));
-
- coder->specs[coder->specs_count - 1] = *spec;
-
- memset(spec, 0, sizeof(encoding_spec));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage en cours de libération. *
-* *
-* Description : Libère de la mémoire une spécification d'encodage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_encoding_spec(encoding_spec *spec)
-{
- free_all_syntax_items_in_spec(spec);
-
- free_all_bitfields_in_spec(spec);
-
- free_all_conversion_in_spec(spec);
-
- free_all_coder_spec_rules(spec);
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES CHAMPS DE BITS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* name = désignation humaine du champ remarqué. *
-* length = taille du champ à mémoriser. *
-* *
-* Description : Note la présence d'un champ remarquable dans une définition. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void register_named_field_in_coder(rented_coder *coder, char *name, unsigned int length)
-{
- encoding_spec *spec; /* Définition à compléter */
- dec_bitfield *field; /* Nouveau champ à constituer */
-
- spec = coder->cur_spec;
-
- assert((spec->curpos + length) < 64);
-
- spec->bitfields = (dec_bitfield *)realloc(spec->bitfields,
- ++spec->bf_count * sizeof(dec_bitfield));
-
- field = &spec->bitfields[spec->bf_count - 1];
-
- field->name = make_string_lower(name);
- field->start = spec->curpos;
- field->length = length;
-
- spec->curpos += length;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage à parcourir. *
-* name = désignation humaine du champ à retrouver. *
-* *
-* Description : Recherche un champ donné dans une définition. *
-* *
-* Retour : Structure associée au champ trouvé ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const dec_bitfield *find_named_field_in_spec(const encoding_spec *spec, const char *name)
-{
- dec_bitfield *result; /* Champ de bits à retourner */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < spec->bf_count && result == NULL; i++)
- if (strcmp(spec->bitfields[i].name, name) == 0)
- result = &spec->bitfields[i];
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* val = valeur du bit à prendre en compte. *
-* *
-* Description : Note la présence d'un bit invariable dans une définition. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void register_bit_in_coder(rented_coder *coder, int val)
-{
- encoding_spec *spec; /* Définition à compléter */
-
- spec = coder->cur_spec;
-
- assert(spec->curpos < 64);
-
- spec->bits |= (val ? 1 : 0) << spec->curpos;
- spec->mask |= 1 << spec->curpos;
-
- spec->curpos++;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage en cours de libération. *
-* *
-* Description : Libère de la mémoire toutes les champs de bits définis. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_all_bitfields_in_spec(encoding_spec *spec)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < spec->bf_count; i++)
- free(spec->bitfields[i].name);
-
- if (spec->bitfields != NULL)
- {
- free(spec->bitfields);
- spec->bitfields = NULL;
- }
-
- spec->bf_count = 0;
-
- spec->bits = 0;
- spec->mask = 0;
-
- spec->curpos = 0;
-
-}
-
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* *
-* Description : Indique le nombre de bits traités. *
-* *
-* Retour : Quantité, positive ou nulle. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-unsigned int count_coder_bits(const rented_coder *coder)
-{
- return coder->cur_spec->curpos;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* SYNTAXE DES INSTRUCTIONS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement d'humain. *
-* name = désignation de l'opérande dans la spécification. *
-* internal = précise si l'opérand est non générique ou non. *
-* *
-* Description : Enregistre la présence d'un nouvel opérande. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void register_syntax_item_in_coder(rented_coder *coder, char *name, bool internal)
-{
- encoding_spec *spec; /* Définition à compléter */
- syntax_item *item; /* Nouvelle prise en compte */
- size_t len; /* Taille du nom fourni */
-
- spec = coder->cur_spec;
-
- spec->items = (syntax_item *)realloc(spec->items, ++spec->items_count * sizeof(syntax_item));
-
- item = &spec->items[spec->items_count - 1];
-
- /* Récupération des drapeaux */
-
- item->flags = SIF_NONE;
-
- for (len = strlen(name); len > 0; len--)
- switch (name[0])
- {
- case '#':
- item->flags |= SIF_DECIMAL;
- memmove(name, name + 1, len);
- break;
-
- default:
- len = 1;
- break;
-
- }
-
- item->name = make_string_lower(name);
- item->internal = internal;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage en cours de libération. *
-* *
-* Description : Libère de la mémoire tous les éléments de syntaxe. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_all_syntax_items_in_spec(encoding_spec *spec)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < spec->items_count; i++)
- free(spec->items[i].name);
-
- if (spec->items != NULL)
- {
- free(spec->items);
- spec->items = NULL;
- }
-
- spec->items_count = 0;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONVERSION DES ARGUMENTS */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* dest = désignation de la variable de destination. *
-* func = nom de la fonction assurant le calcul de valeur. *
-* arg = argument à fournir à cette fonction. *
-* *
-* Description : Enregistre la function de conversion du brut à l'utile. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void register_conversion_in_coder(rented_coder *coder, char *dest, char *func, char *arg)
-{
- encoding_spec *spec; /* Définition à compléter */
- conv_func *conv; /* Nouvelle prise en compte */
-
- spec = coder->cur_spec;
-
- spec->conversions = (conv_func *)realloc(spec->conversions, ++spec->conv_count * sizeof(conv_func));
-
- conv = &spec->conversions[spec->conv_count - 1];
-
- conv->dest = make_string_lower(dest);
- conv->func = func;
- conv->arg = make_string_lower(arg);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage en cours de libération. *
-* *
-* Description : Libère de la mémoire toutes les conversions enregistrées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_all_conversion_in_spec(encoding_spec *spec)
-{
- size_t i; /* Boucle de parcours */
- conv_func *conv; /* Conversion à traiter */
-
- for (i = 0; i < spec->conv_count; i++)
- {
- conv = &spec->conversions[i];
-
- free(conv->dest);
- free(conv->func);
- free(conv->arg);
-
- }
-
- if (spec->conversions != NULL)
- {
- free(spec->conversions);
- spec->conversions = NULL;
- }
-
- spec->conv_count = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'un encodage à consulter. *
-* dest = désignation d'une variable de destination. *
-* *
-* Description : Recherche une fonction converrtissant une donnée brute. *
-* *
-* Retour : Structure de conversion trouvée ou NULL en cas d'échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static const conv_func *find_conversion_in_coder_spec(const encoding_spec *spec, const char *dest)
-{
- const conv_func *result; /* Conversion à renvoyer */
- size_t i; /* Boucle de parcours */
-
- result = NULL;
-
- for (i = 0; i < spec->conv_count && result == NULL; i++)
- if (strcmp(spec->conversions[i].dest, dest) == 0)
- result = &spec->conversions[i];
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* CONDITIONS ET CONSEQUENCES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : variable = désignation de la variable à manipuler. *
-* comp = type de comparaison à utiliser. *
-* bvalue = valeur binaire à comparer. *
-* *
-* Description : Crée une expression conditionnelle simple. *
-* *
-* Retour : Structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue)
-{
- cond_expr *result; /* Structure à retourner */
-
- result = (cond_expr *)calloc(1, sizeof(cond_expr));
-
- result->is_simple = true;
-
- result->simple.variable = make_string_lower(variable);
- result->simple.comp = comp;
- result->simple.bvalue = bvalue;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : a = première expression à intégrer. *
-* operator = type de comparaison à utiliser. *
-* b = second expression à intégrer. *
* *
-* Description : Crée une expression conditionnelle composée. *
+* Description : Fournit un lien vers les spécifications courantes. *
* *
-* Retour : Structure mise en place. *
+* Retour : Spécification en cours d'édition. *
* *
* Remarques : - *
* *
******************************************************************************/
-cond_expr *build_composed_cond_expression(cond_expr *a, CondOpType operator, cond_expr *b)
+encoding_spec *get_current_encoding_spec(const rented_coder *coder)
{
- cond_expr *result; /* Structure à retourner */
-
- result = (cond_expr *)calloc(1, sizeof(cond_expr));
-
- result->is_simple = false;
-
- result->composed.a = a;
- result->composed.operator = operator;
- result->composed.b = b;
-
- return result;
+ return coder->cur_spec;
}
/******************************************************************************
* *
-* Paramètres : expr = représentation d'expression à traiter. *
-* *
-* Description : Libère de la mémoire une expression conditionnelle. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_cond_expr(cond_expr *expr)
-{
- if (expr->is_simple)
- {
- free(expr->simple.variable);
- free(expr->simple.bvalue);
- }
- else
- {
- free_cond_expr(expr->composed.a);
- free_cond_expr(expr->composed.b);
- }
-
- free(expr);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'un encodage à consulter. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* expr = expression simple ou composée à transposer. *
-* *
-* Description : Traduit en code une expression de condition. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool write_cond_expr(const encoding_spec *spec, int fd, const cond_expr *expr)
-{
- bool result; /* Bilan à renvoyer */
- const dec_bitfield *bf; /* Champ de bits de définition */
-
- result = true;
-
- dprintf(fd, "(");
-
- if (expr->is_simple)
- {
- bf = find_named_field_in_spec(spec, expr->simple.variable);
- if (bf == NULL)
- {
- fprintf(stderr, "Error: no bitfield defined the requested variable '%s'.\n", expr->simple.variable);
- result = false;
- goto wce_exit;
- }
-
- if (bf->length != strlen(expr->simple.bvalue))
- {
- fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n",
- expr->simple.variable, bf->length, strlen(expr->simple.bvalue));
- result = false;
- goto wce_exit;
- }
-
- dprintf(fd, "raw_%s", expr->simple.variable);
-
- switch (expr->simple.comp)
- {
- case CCT_EQUAL:
- dprintf(fd, " == ");
- break;
- case CCT_DIFF:
- dprintf(fd, " != ");
- break;
- }
-
- dprintf(fd, "b%s", expr->simple.bvalue);
-
- }
- else
- {
- result = write_cond_expr(spec, fd, expr->composed.a);
- if (!result) goto wce_exit;
-
- switch (expr->composed.operator)
- {
- case COT_AND:
- dprintf(fd, " && ");
- break;
- case COT_OR:
- dprintf(fd, " || ");
- break;
- }
-
- result = write_cond_expr(spec, fd, expr->composed.b);
- if (!result) goto wce_exit;
-
- }
-
- dprintf(fd, ")");
-
- wce_exit:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain.*
-* expr = représentation d'expression à conserver. *
-* action = conséquence associée à la règle. *
-* details = éventuel complément d'informations. *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* prefix = distinction principale entre les définitions. *
+* index = distinction secondaire entre les définitions. *
* *
-* Description : Ajoute une règle complète à la définition d'un codage. *
+* Description : Enregistre une définition supplémentaire. *
* *
* Retour : - *
* *
@@ -1142,129 +345,18 @@ static bool write_cond_expr(const encoding_spec *spec, int fd, const cond_expr *
* *
******************************************************************************/
-void add_conditional_rule_to_coder(rented_coder *coder, cond_expr *expr, CondActionType action, const char *details)
+void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index)
{
encoding_spec *spec; /* Définition à compléter */
- extra_rule *rule; /* Nouvelle prise en compte */
spec = coder->cur_spec;
- spec->rules = (extra_rule *)realloc(spec->rules, ++spec->rules_count * sizeof(extra_rule));
+ define_encoding_spec_code_name(spec, prefix, index);
- rule = &spec->rules[spec->rules_count - 1];
+ coder->specs = (encoding_spec **)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec *));
+ coder->specs[coder->specs_count - 1] = spec;
- rule->expr = expr;
- rule->action = action;
- rule->details = make_callable(details, false);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : spec = spécification d'encodage à traiter. *
-* *
-* Description : Libère de la mémoire des règles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void free_all_coder_spec_rules(encoding_spec *spec)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < spec->rules_count; i++)
- {
- free_cond_expr(spec->rules[i].expr);
-
- if (spec->rules[i].details)
- free(spec->rules[i].details);
-
- }
-
- if (spec->rules != NULL)
- {
- free(spec->rules);
- spec->rules = NULL;
- }
-
- spec->rules_count = 0;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* spec = spécification servant de base à l'opération. *
-* exit = exprime le besoin d'une voie de sortie. [OUT] *
-* *
-* Description : Traduit en code les éventuelles règles présentes. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool write_coder_spec_rules(const rented_coder *coder, int fd, const encoding_spec *spec, bool *exit)
-{
- bool result; /* Bilan à remonter */
- const extra_rule *rule; /* Règle en cours d'écriture */
- size_t i; /* Boucle de parcours */
-
- result = true;
-
- *exit = false;
-
- for (i = 0; i < spec->rules_count; i++)
- {
- rule = &spec->rules[i];
-
- dprintf(fd, "\t\tif ");
-
- result = write_cond_expr(spec, fd, rule->expr);
- if (!result) break;
-
- dprintf(fd, "\n");
- dprintf(fd, "\t\t{\n");
-
- switch (rule->action)
- {
- case CAT_SEE:
-
- if (rule->details == NULL)
- {
- fprintf(stderr, "Error: directive 'see' must provide additional details.\n");
- result = false;
- goto wcsr_exit;
- }
-
- dprintf(fd, "\t\t\tinstr = armv7_read_instr_%s", rule->details);
-
- /* TODO : adapter les paramètres d'appel selon le 'coder' */
- dprintf(fd, "(_raw);\n");
-
- dprintf(fd, "\t\t\tgoto quick_exit;\n");
-
- *exit = true;
- break;
-
- }
-
- dprintf(fd, "\t\t}\n");
-
- dprintf(fd, "\n");
-
- }
-
- wcsr_exit:
-
- return result;
+ coder->cur_spec = create_encoding_spec();
}
@@ -1360,7 +452,7 @@ bool dump_all_routines_using_coder(const rented_coder *coder)
{
bool result; /* Bilan à retourner */
size_t i; /* Boucle de parcours */
- string_exch *encoding; /* Type d'encodage visé */
+ const string_exch *encoding; /* Type d'encodage visé */
bool exist; /* Présence du fichier visé ? */
int header_fd; /* Fichier de déclarations */
char *dash; /* Présence d'un tiret ? */
@@ -1369,9 +461,9 @@ bool dump_all_routines_using_coder(const rented_coder *coder)
result = true;
- for (i = 0; i < coder->encodings_count && result; i++)
+ for (i = 0; i < count_encodings(coder->pp) && result; i++)
{
- encoding = &coder->encodings[i];
+ encoding = find_encoding(coder->pp, i);
/* Fichier de déclarations */
@@ -1462,6 +554,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
unsigned int wide; /* Taille des mots */
size_t i; /* Boucle de parcours */
encoding_spec *spec; /* Définition à traiter */
+ coding_bits *bits; /* Gestionnaire de bits */
size_t maxlen; /* Taille à compléter */
result = true;
@@ -1474,12 +567,13 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
for (i = 0; i < coder->specs_count; i++)
{
- spec = &coder->specs[i];
+ spec = coder->specs[i];
- if (strcmp(encoding->src, spec->prefix) != 0)
+ if (!has_encoding_spec_prefix(spec, encoding->src))
continue;
- wide = spec->curpos;
+ bits = get_bits_in_encoding_spec(spec);
+ wide = count_coded_bits(bits);
break;
}
@@ -1532,12 +626,12 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
for (i = 0; i < coder->specs_count && result; i++)
{
- spec = &coder->specs[i];
+ spec = coder->specs[i];
- if (strcmp(encoding->src, spec->prefix) != 0)
+ if (!has_encoding_spec_prefix(spec, encoding->src))
continue;
- result = write_coder_spec_disass(coder, cfd, spec, keyword, wide);
+ result = write_encoding_spec_disass(spec, cfd, coder->arch, coder->ins, coder->details, wide, coder->pp);
}
@@ -1554,325 +648,3 @@ 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 de l'humain.*
-* fd = descripteur d'un flux ouvert en écriture. *
-* spec = spécification servant de base à l'opération. *
-* keyword = nom clef de l'instruction utilisable dans du code. *
-* wide = taille des mots manipulés (en bits). *
-* *
-* Description : Traduit en code une sous-fonction de désassemblage. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool write_coder_spec_disass(const rented_coder *coder, int fd, const encoding_spec *spec, const char *keyword, unsigned int wide)
-{
- size_t i; /* Boucle de parcours */
- dec_bitfield *bf; /* Accès confortable à un champ*/
- bool exit; /* Inclusion de sortie rapide ?*/
- syntax_item *item; /* Lien vers un opérande */
- regex_t preg; /* Expression régulière */
- int ret; /* Bilan d'une manipulation */
- const conv_func *conv; /* Moyen de conversion du brut */
- const char *callable; /* Fonction à appeler */
- bool rebuild; /* Construction complexe */
- regmatch_t pmatch[3]; /* Correspondances de chaînes */
- size_t cmplen; /* Taille de comparaison */
- char *cast; /* Macro de transtypage */
-
- dprintf(fd, "\tGArchInstruction *%s_decode_%s%s_%s%u(uint%u_t _raw)\n",
- coder->arch, keyword, coder->details, spec->prefix, spec->index, wide);
-
- dprintf(fd, "\t{\n");
-
- dprintf(fd, "\t\tGArchInstruction *instr;\n");
-
- /* Déclaration des champs à retrouver */
-
- for (i = 0; i < spec->bf_count; i++)
- dprintf(fd, "\t\tuint%u_t raw_%s;\n", wide, spec->bitfields[i].name);
-
- for (i = 0; i < spec->items_count; i++)
- if (!spec->items[i].internal)
- {
- dprintf(fd, "\t\tGArchOperand *op;\n");
- break;
- }
-
- dprintf(fd, "\n");
-
- /* Vérification que le décodage est possible */
-
- dprintf(fd, "\t\tif ((raw & 0x%" PRIx64 ") != 0x%" PRIx64 ") return NULL;\n", spec->mask, spec->bits);
-
- dprintf(fd, "\n");
-
- /* Définition des champs bruts */
-
- for (i = 0; i < spec->bf_count; i++)
- {
- bf = &spec->bitfields[i];
- dprintf(fd, "\t\traw_%s = (_raw >> %u) & 0x%llx;\n", bf->name, bf->start, (1ull << bf->length) - 1);
- }
-
- dprintf(fd, "\n");
-
- /* Inclusion des éventuelles règles */
-
- if (!write_coder_spec_rules(coder, fd, spec, &exit))
- return false;
-
- /* Création de l'instruction en elle-même */
-
- dprintf(fd, "\t\tinstr = g_%s_instruction_new(\"%s\");\n", coder->arch, coder->ins);
-
- dprintf(fd, "\n");
-
- /* Création des opérandes */
-
- bool build_arg_if_needed(const conv_func *conv)
- {
-
- /* TODO : concaténation... */
-
- return false;
-
- }
-
- ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
- if (ret != 0)
- {
- fprintf(stderr, "Internal error: bad regular expression.\n");
- return false;
- }
-
-
- for (i = 0; i < spec->items_count; i++)
- {
- item = &spec->items[i];
-
- conv = find_conversion_in_coder_spec(spec, item->name);
- if (conv == NULL)
- {
- fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name);
- return false;
- }
-
- callable = find_macro_in_coder(coder, conv->func);
- if (callable == NULL)
- {
- fprintf(stderr, "Error: expected function to store '%s'.\n", item->name);
- return false;
- }
-
- rebuild = build_arg_if_needed(conv);
-
- if (item->internal)
- {
- ret = regexec(&preg, callable, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
- if (ret == REG_NOMATCH)
- {
- fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callable);
- return false;
- }
-
- /**
- * La variable de résultat est de type 'GArchInstruction',
- * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
- */
-
- cmplen = MAX(strlen(coder->arch), pmatch[2].rm_eo - pmatch[2].rm_so);
-
- if (strncmp("arch", &callable[pmatch[2].rm_so], cmplen) == 0)
- dprintf(fd, "\t\tif (!%s(instr, %s%s))\n",
- callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg);
-
- else
- {
- cast = strndup(&callable[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
-
- cast = make_string_upper(cast);
-
- dprintf(fd, "\t\tif (!%s(%s(instr), %s%s))\n",
- callable, cast, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg);
-
- free(cast);
-
- }
-
- dprintf(fd, "\t\t\tgoto bad_exit;\n");
-
- }
-
- else
- {
- if (strchr(callable, '(') == NULL)
- dprintf(fd, "\t\top = %s(%s%s);\n",
- callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg);
- else
- dprintf(fd, "\t\top = %s%s%s);\n",
- callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg);
- dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n");
-
- dprintf(fd, "\n");
-
- if (item->flags & SIF_DECIMAL)
- dprintf(fd, "\t\tg_imm_operand_set_display(G_IMM_OPERAND(op), IOD_DEC);\n");
-
- dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n");
-
- }
-
- dprintf(fd, "\n");
-
- }
-
- regfree(&preg);
-
- /* Conclusion de la procédure */
-
- if (exit)
- {
- dprintf(fd, "\t quick_exit:\n");
- dprintf(fd, "\n");
- }
-
- dprintf(fd, "\t\treturn instr;\n");
-
- dprintf(fd, "\n");
-
- dprintf(fd, "\t bad_exit:\n");
-
- dprintf(fd, "\n");
-
- dprintf(fd, "\t\tg_object_unref(G_OBJECT(instr));\n");
- dprintf(fd, "\t\treturn NULL;\n");
-
- dprintf(fd, "\n");
-
- dprintf(fd, "\t}\n");
-
- dprintf(fd, "\n");
-
- dprintf(fd, "\tif (result == NULL)\n");
- dprintf(fd, "\t\tresult = %s_decode_%s%s_%s%u(raw);\n",
- coder->arch, keyword, coder->details, spec->prefix, spec->index);
-
- dprintf(fd, "\n");
-
- return true;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* MANIPULATIONS DE CHAINES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : str = chaîne de caractères à manipuler. [OUT] *
-* *
-* Description : Bascule toute une chaîne de caractères en (min|maj)uscules. *
-* *
-* Retour : Pointeur sur la chaîne fournie. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *_make_string_xxx(char *str, int (* fn) (int))
-{
- size_t max; /* Empleur du parcours */
- size_t i; /* Boucle de parcours */
-
- max = strlen(str);
-
- for (i = 0; i < max; i++)
- str[i] = fn(str[i]);
-
- return str;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : raw = données brutes en provenance de l'analyseur. *
-* details = indique la nature de la chaîne à traiter. *
-* *
-* Description : Traduit une chaîne en élément de fonction C. *
-* *
-* Retour : Chaîne à libérer de la mémoire après usage. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static char *make_callable(const char *raw, bool details)
-{
- char *result; /* Nom formaté à retourner */
- size_t max; /* Empleur du parcours */
- size_t i; /* Boucle de parcours */
-
- result = strdup(raw);
-
- max = strlen(result);
-
- /* Première passe : on vire les virgules */
-
- for (i = 0; i < max; i++)
- if (result[i] == ',')
- {
- memmove(result + i, result + i + 1, max - i - 1);
- max--;
- }
-
- result[max] = '\0';
-
- /* Deuxième passe : on bascule en minuscules */
-
- result = make_string_lower(result);
-
- /* Troisième passe : on remplace les mauvais caractères */
-
- for (i = 0; i < max; i++)
- switch (result[i])
- {
- case 'a' ... 'z':
- case '0' ... '9':
- break;
- case '-':
- result[i] = '_';
- break;
- default:
- result[i] = (i + 1 == max ? '\0' : '_');
- break;
- }
-
- /**
- * Dernière passe : on s'assure que le premier caractère n'est pas une lettre.
- * On ajoute ici le préfixe '_' utilisé lors de la génération de prototypes ;
- * en cas d'absence de détails, on ne se retrouve ainsi pas avec un '_' isolé.
- */
-
- if (details && result[0] != '_')
- {
- max = strlen(result) + 1;
- result = (char *)realloc(result, max);
- memmove(result + 1, result, max - 1);
- result[0] = '_';
- }
-
- return result;
-
-}
diff --git a/tools/coder.h b/tools/coder.h
index c96f787..e72764c 100644
--- a/tools/coder.h
+++ b/tools/coder.h
@@ -28,6 +28,10 @@
#include <stdbool.h>
+#include "pproc.h"
+#include "spec.h"
+
+
/* Suivi des constructions */
typedef struct _rented_coder rented_coder;
@@ -55,11 +59,8 @@ 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 *);
-/* Enregistre une correspondance en matière d'encodage. */
-void register_encoding_in_coder(rented_coder *, const char *, const char *);
-
-/* Constitue la matière d'un système de macros. */
-void define_macro_for_coder(rented_coder *, const char *, 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 *);
@@ -69,6 +70,8 @@ void save_notes_for_coder(rented_coder *, char *, char *, const char *);
/* --------------------------- REPRESENTATION D'ENCODAGES --------------------------- */
+/* Fournit un lien vers les spécifications courantes. */
+encoding_spec *get_current_encoding_spec(const rented_coder *);
/* Enregistre une définition supplémentaire. */
void push_encoding_spec(rented_coder *, char *, unsigned int);
@@ -85,7 +88,7 @@ void register_named_field_in_coder(rented_coder *, char *, unsigned int);
void register_bit_in_coder(rented_coder *, int);
/* Indique le nombre de bits traités. */
-unsigned int count_coder_bits(const rented_coder *);
+//unsigned int count_coder_bits(const rented_coder *);
@@ -101,49 +104,13 @@ void register_syntax_item_in_coder(rented_coder *, char *, bool);
/* Enregistre la function de conversion du brut à l'utile. */
-void register_conversion_in_coder(rented_coder *, char *, char *, char *);
+void register_conversion_in_coder(rented_coder *, conv_func *);
/* --------------------------- CONDITIONS ET CONSEQUENCES --------------------------- */
-/* Types de comparaison */
-typedef enum _CondCompType
-{
- CCT_EQUAL, /* Egalité '==' */
- CCT_DIFF /* Différence '!=' */
-
-} CondCompType;
-
-/* Types de combinaison d'expressions */
-typedef enum _CondOpType
-{
- COT_AND, /* Combinaison ET ('&&') */
- COT_OR /* Combinaison OU ('||') */
-
-} CondOpType;
-
-/* Conséquence en cas de condition remplie */
-typedef enum _CondActionType
-{
- CAT_SEE /* Renvoi vers une instruction */
-
-} CondActionType;
-
-
-/* Expression d'une condition */
-typedef struct _cond_expr cond_expr;
-
-
-/* Crée une expression conditionnelle simple. */
-cond_expr *build_simple_cond_expression(char *, CondCompType, char *);
-
-/* Crée une expression conditionnelle composée. */
-cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
-
-/* Ajoute une règle complète à la définition d'un codage. */
-void add_conditional_rule_to_coder(rented_coder *, cond_expr *, CondActionType, const char *);
diff --git a/tools/conv.c b/tools/conv.c
new file mode 100644
index 0000000..323f63d
--- /dev/null
+++ b/tools/conv.c
@@ -0,0 +1,1640 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * conv.c - substitutions de valeurs depuis un contenu binaire
+ *
+ * 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 "conv.h"
+
+
+#include <assert.h>
+#include <ctype.h>
+#include <malloc.h>
+#include <regex.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+#include "helpers.h"
+
+
+
+
+
+/* Types d'expressions représentés */
+typedef enum _ConvExprType
+{
+ CET_NAME, /* Désignation de variable */
+ CET_NUMBER, /* Valeur codée en dur */
+ CET_COMPOSED, /* Agrégat de champs divers */
+ CET_UNARY, /* Opération unaire */
+ CET_BINARY, /* Opération binaire */
+
+ CET_COUNT
+
+} ConvExprType;
+
+
+/* Représentation d'une expression de conversion */
+struct _conv_expr_t
+{
+ ConvExprType type;
+
+ bool declared; /* Expression déjà déclarée ? */
+ bool defined; /* Expression déjà définie ? */
+
+ union
+ {
+ /* CET_NAME */
+ char *name; /* Désignation de variable */
+
+ /* CET_NUMBER */
+ unsigned long number; /* Valeur durablement définie */
+
+ /* CET_COMPOSED */
+ struct
+ {
+ char **comp_items; /* Elements à agréger */
+ size_t comp_count; /* Quantité de ces éléments */
+ };
+
+ /* CET_UNARY */
+ struct
+ {
+ conv_expr_t *un_expr; /* Expression à traiter */
+ ConvUnaryOperation un_op; /* Type d'opération à mener */
+
+ };
+
+ /* CET_BINARY */
+ struct
+ {
+ conv_expr_t *bin_expr1; /* Expression à traiter */
+ conv_expr_t *bin_expr2; /* Expression à traiter */
+ ConvBinaryOperation bin_op; /* Type d'opération à mener */
+
+ };
+
+ };
+
+};
+
+
+/* Visite une expression en traitant en premier ses composantes. */
+typedef bool (* visit_expr_fc) (conv_expr_t *, int, const coding_bits *, const conv_list *, void *);
+
+
+/* Détermine la taille en bits d'une expression donnée. */
+static bool compute_conv_expr_size(const conv_expr_t *, const coding_bits *, const conv_list *, unsigned int *);
+
+/* Visite une expression en traitant en premier ses composantes. */
+static bool visit_conv_expr(conv_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *);
+
+/* Retrouve si elle existe une variable manipulée. */
+static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **);
+
+/* S'assure du marquage des expressions pre-requises. */
+static bool ensure_conv_expr_content_fully_marked(conv_expr_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+static bool ensure_conv_expr_content_fully_declared(conv_expr_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+static bool ensure_conv_expr_content_fully_defined(conv_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit une expression utilisée dans une conversion. */
+static bool define_conv_expr(conv_expr_t *, int, const coding_bits *, const conv_list *);
+
+
+
+/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+struct _conv_arg_list_t
+{
+ conv_expr_t **items; /* Liste d'expressions */
+ size_t count; /* Taille de cette liste */
+
+};
+
+
+/* S'assure du marquage des expressions pre-requises. */
+static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit les variables associées à un appel de fonction. */
+static bool define_arg_list(conv_arg_list_t *, int, const coding_bits *, const conv_list *);
+
+
+
+/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */
+
+
+/* Fonction de conversion */
+struct _conv_func
+{
+ bool declared; /* Expression déjà déclarée ? */
+ bool defined; /* Expression déjà définie ? */
+
+ char *dest; /* Variable de destination */
+
+ bool is_expr; /* Choix du contenu réel */
+
+ union
+ {
+ conv_expr_t *expr; /* Valeur expressive directe */
+
+ struct
+ {
+ char *name; /* Fonction de conversion */
+ conv_arg_list_t *args; /* Liste des arguments */
+
+ };
+
+ };
+
+};
+
+
+/* Détermine la taille en bits du résultat d'une fonction. */
+static bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *);
+
+
+
+
+
+
+#define delete_conv_expr(e)
+
+
+
+
+
+
+/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
+
+
+/* Liste des fonctions de conversions présentes */
+struct _conv_list
+{
+ conv_func **functions; /* Fonctions de conversion */
+ size_t func_count; /* Nombre de ces fonctions */
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation d'une variable quelconque. *
+* *
+* Description : Référence une variable en tant qu'expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *build_conv_expr_from_name(char *name)
+{
+ conv_expr_t *result; /* Structure à retourner */
+
+ result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
+
+ result->type = CET_NAME;
+
+ result->name = make_string_lower(name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : number = valeur à conserver dans sa forme brute. *
+* *
+* Description : Conserve une valeur en tant qu'expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *build_conv_expr_from_number(unsigned long number)
+{
+ conv_expr_t *result; /* Structure à retourner */
+
+ result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
+
+ result->type = CET_NUMBER;
+
+ result->number = number;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item1 = premier élément à agréger. *
+* item2 = second élément à agréger. *
+* *
+* Description : Construit une base d'expression de conversion composée. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *build_composed_conv_expr(char *item1, char *item2)
+{
+ conv_expr_t *result; /* Structure à retourner */
+
+ result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
+
+ result->type = CET_COMPOSED;
+
+ result->comp_items = (char **)calloc(2, sizeof(char *));
+ result->comp_count = 2;
+
+ result->comp_items[0] = make_string_lower(item1);
+ result->comp_items[1] = make_string_lower(item2);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression déjà en place à compléter. *
+* item = nouvel élément à agréger. *
+* *
+* Description : Etend une base d'expression de conversion composée. *
+* *
+* Retour : Expression en place et mise à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *extend_composed_conv_expr(conv_expr_t *expr, char *item)
+{
+ assert(expr->type == CET_COMPOSED);
+
+ expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *));
+
+ expr->comp_items[expr->comp_count - 1] = make_string_lower(item);
+
+ return expr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à encapsuler. *
+* op = opération unaire à associer à l'opération. *
+* *
+* Description : Traduit une opération unaire sur expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *build_unary_conv_expr(conv_expr_t *expr, ConvUnaryOperation op)
+{
+ conv_expr_t *result; /* Structure à retourner */
+
+ result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
+
+ result->type = CET_UNARY;
+
+ result->un_expr = expr;
+ result->un_op = op;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr1 = première expression à encapsuler. *
+* expr2 = seconde expression à encapsuler. *
+* op = opération binaire à associer à l'opération. *
+* *
+* Description : Traduit une opération binaire sur expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_expr_t *build_binary_conv_expr(conv_expr_t *expr1, conv_expr_t *expr2, ConvBinaryOperation op)
+{
+ conv_expr_t *result; /* Structure à retourner */
+
+ result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
+
+ result->type = CET_BINARY;
+
+ result->bin_expr1 = expr1;
+ result->bin_expr2 = expr2;
+ result->bin_op = op;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à consulter. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* size = taille déterminée avec précision. [OUT] *
+* *
+* Description : Détermine la taille en bits d'une expression donnée. *
+* *
+* Retour : true si la taille a pu être déterminée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool compute_conv_expr_size(const conv_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *field; /* Eventuel champ brut associé */
+ conv_func *func; /* Eventuelle fonction liée */
+ size_t i; /* Boucle de parcours */
+ unsigned int tmp; /* Stockage temporaire */
+
+ switch (expr->type)
+ {
+ case CET_NAME:
+
+ result = find_var_by_name(bits, list, expr->name, &field, &func);
+
+ if (result)
+ {
+ if (field != NULL)
+ *size = get_raw_bitfield_length(field);
+ else
+ result = compute_conv_func_size(func, bits, list, size);
+ }
+
+ break;
+
+ case CET_COMPOSED:
+
+ result = true;
+ *size = 0;
+
+ for (i = 0; i < expr->comp_count && result; i++)
+ {
+ if (isdigit(expr->comp_items[i][0]))
+ *size += strlen(expr->comp_items[i]);
+
+ else
+ {
+ if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func))
+ result = false;
+
+ else
+ {
+ if (field != NULL)
+ *size += get_raw_bitfield_length(field);
+ else
+ {
+ result = compute_conv_func_size(func, bits, list, &tmp);
+ *size += tmp;
+ }
+ }
+
+ }
+
+ }
+
+ break;
+
+ case CET_UNARY:
+ result = compute_conv_expr_size(expr->un_expr, bits, list, size);
+ break;
+
+ case CET_BINARY:
+
+ result = compute_conv_expr_size(expr->bin_expr1, bits, list, &tmp);
+
+ if (result)
+ result = compute_conv_expr_size(expr->bin_expr1, bits, list, size);
+
+ if (tmp > *size) *size = tmp;
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* data = éventuelle donnée à transmettre à chaque visite. *
+* *
+* Description : Visite une expression en traitant en premier ses composantes.*
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool visit_conv_expr(conv_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data)
+{
+ bool result; /* Bilan à retourner */
+
+ switch (expr->type)
+ {
+ case CET_UNARY:
+ result = visit_conv_expr(expr->un_expr, visit, fd, bits, list, data);
+ break;
+
+ case CET_BINARY:
+ result = visit_conv_expr(expr->bin_expr1, visit, fd, bits, list, data);
+ result = visit_conv_expr(expr->bin_expr2, visit, fd, bits, list, data);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ result &= visit(expr, fd, bits, list, data);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* name = déssignation de la variable recherchée. *
+* field = éventuel élement brut de décodage. *
+* func = éventuelle fonction de conversion pour intermédiaire.*
+* *
+* Description : Retrouve si elle existe une variable manipulée. *
+* *
+* Retour : Bilan des recherches : trouvaille ou non ? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *cached_field; /* Champ, version cachée */
+ conv_func *cached_func; /* Fonction, version cachée */
+
+ cached_field = find_named_field_in_bits(bits, name);
+ result = (cached_field != NULL);
+
+ if (!result)
+ {
+ cached_func = find_named_conv_in_list(list, name);
+ result = (cached_func != NULL);
+ }
+ else
+ cached_func = NULL;
+
+ if (field != NULL) *field = cached_field;
+ if (func != NULL) *func = cached_func;
+
+ if (!result)
+ fprintf(stderr, "Variable '%s' not found!\n", name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : S'assure du marquage des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_conv_expr_content_fully_marked(conv_expr_t *expr, const coding_bits *bits, const conv_list *list)
+{
+ bool mark_sub_expr(conv_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ raw_bitfield *field; /* Eventuel champ brut associé */
+
+ found = find_var_by_name(bts, lst, name, &field, NULL);
+
+ if (found && field != NULL)
+ mark_raw_bitfield_as_used(field);
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = mark_by_name(bits, lst, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = mark_by_name(bits, lst, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ return result;
+
+ }
+
+ return visit_conv_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : S'assure de la déclaration des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_conv_expr_content_fully_declared(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool declare_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+ if (sub->declared) return true;
+
+ bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ conv_func *func; /* Eventuelle fonction liée */
+
+ found = find_var_by_name(bts, lst, name, NULL, &func);
+
+ if (found && func != NULL)
+ {
+ dprintf(_f, "\t\tuint%u_t val_%s;\n", _wide, name);
+ found = declare_conv_func(func, _f, _bts, _lst, _wide);
+ }
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = declare_by_name(f, bits, lst, *wide, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ printf("... trying to declare... '%s'\n", sub->comp_items[i]);
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ sub->declared = result;
+
+ return result;
+
+ }
+
+ return visit_conv_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : S'assure de la définition des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_conv_expr_content_fully_defined(conv_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ typedef struct _def_info
+ {
+ const char *arch;
+ const pre_processor *pp;
+
+ } def_info;
+
+ def_info info; /* Transmissions au visiteur */
+
+ bool define_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+ if (sub->defined) return true;
+
+ bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ conv_func *func; /* Eventuelle fonction liée */
+
+ found = find_var_by_name(bts, lst, name, NULL, &func);
+
+ if (found && func != NULL)
+ found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp);
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = define_by_name(f, bits, lst, info, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = define_by_name(f, bits, lst, info, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ sub->defined = result;
+
+ return result;
+
+ }
+
+ info.arch = arch;
+ info.pp = pp;
+
+ return visit_conv_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Définit une expression utilisée dans une conversion. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool define_conv_expr(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *field; /* Eventuel champ brut associé */
+ conv_func *func; /* Eventuelle fonction liée */
+ unsigned int max_size; /* Quantité de bits totale */
+ size_t i; /* Boucle de parcours */
+ const char *cname; /* Raccourci de confort */
+ unsigned int used_size; /* Quantité de bits utilisée */
+
+ result = true;
+
+ switch (expr->type)
+ {
+ case CET_NAME:
+
+ if (!find_var_by_name(bits, list, expr->name, &field, &func))
+ result = false;
+
+ else
+ {
+ if (field != NULL)
+ dprintf(fd, "raw_%s", expr->name);
+ else
+ dprintf(fd, "val_%s", expr->name);
+ }
+
+ break;
+
+ case CET_NUMBER:
+ dprintf(fd, "%lu", expr->number);
+ break;
+
+ case CET_COMPOSED:
+
+ result = compute_conv_expr_size(expr, bits, list, &max_size);
+
+ printf("MAX SIZE :: %u\n", max_size);
+
+ for (i = 0; i < expr->comp_count && result; i++)
+ {
+ cname = expr->comp_items[i];
+
+ if (i > 0)
+ dprintf(fd, " | ");
+
+ /* Constante binaire ? */
+ if (isdigit(cname[0]))
+ {
+ max_size -= strlen(cname);
+
+ if (max_size == 0)
+ dprintf(fd, "b%s", cname);
+ else
+ dprintf(fd, "b%s << %u", cname, max_size);
+
+ }
+
+ /* Ou variable définie ? */
+ else
+ {
+ result = find_var_by_name(bits, list, cname, &field, &func);
+
+ if (result)
+ {
+ if (field != NULL)
+ used_size = get_raw_bitfield_length(field);
+ else
+ /*result = */compute_conv_func_size(func, bits, list, &used_size);
+
+ max_size -= used_size;
+
+ if (field != NULL)
+ {
+ if (max_size == 0)
+ dprintf(fd, "raw_%s", cname);
+ else
+ dprintf(fd, "raw_%s << %u", cname, max_size);
+ }
+ else
+ {
+ if (max_size == 0)
+ dprintf(fd, "val_%s", cname);
+ else
+ dprintf(fd, "val_%s << %u", cname, max_size);
+ }
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ case CET_UNARY:
+
+ switch (expr->un_op)
+ {
+ case CUO_NOT:
+ dprintf(fd, "!");
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ result &= define_conv_expr(expr->un_expr, fd, bits, list);
+
+ break;
+
+ case CET_BINARY:
+
+ dprintf(fd, "(");
+
+ result = define_conv_expr(expr->bin_expr1, fd, bits, list);
+
+ switch (expr->bin_op)
+ {
+ case CBO_EOR:
+ dprintf(fd, " ^ ");
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ result &= define_conv_expr(expr->bin_expr2, fd, bits, list);
+
+ dprintf(fd, ")");
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* LISTES D'ARGUMENTS DE CONVERSION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression initial pour constituer une liste. *
+* *
+* Description : Crée une liste d'arguments de conversion. *
+* *
+* Retour : Nouvelle structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_arg_list_t *build_conv_arg_list(conv_expr_t *expr)
+{
+ conv_arg_list_t *result; /* Structure à retourner */
+
+ result = (conv_arg_list_t *)calloc(1, sizeof(conv_arg_list_t));
+
+ result->items = (conv_expr_t **)calloc(1, sizeof(conv_expr_t *));
+ result->count = 1;
+
+ result->items[0] = expr;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste d'expressions à supprimer de la mémoire. *
+* *
+* Description : Libère la mémoire occupée par une liste d'expressions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_conv_arg_list(conv_arg_list_t *list)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < list->count; i++)
+ delete_conv_expr(list->items[i]);
+
+ if (list->items != NULL)
+ free(list->items);
+
+ free(list);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] *
+* expr = expression à ajouter à la liste courante. *
+* *
+* Description : Ajoute un élément à une liste d'arguments de conversion. *
+* *
+* Retour : Structure en place mise à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *list, conv_expr_t *expr)
+{
+ list->items = (conv_expr_t **)realloc(list->items, ++list->count * sizeof(conv_expr_t *));
+
+ list->items[list->count - 1] = expr;
+
+ return list;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : S'assure du marquage des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *args, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_conv_expr_content_fully_marked(args->items[i], bits, list);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : S'assure de la déclaration des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_conv_expr_content_fully_declared(args->items[i], fd, bits, list, wide);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : S'assure de la définition des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_conv_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Définit les variables associées à un appel de fonction. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ {
+ if (i > 0) dprintf(fd, ", ");
+ result = define_conv_expr(args->items[i], fd, bits, list);
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONVERSION DES ARGUMENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = désignation de la variable de destination. *
+* expr = expression dont la valeur est à assigner. *
+* *
+* Description : Définit une conversion à partir d'une simple expression. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr)
+{
+ conv_func *result; /* Conversion à retourner */
+
+ result = (conv_func *)calloc(1, sizeof(conv_func));
+
+ result->dest = make_string_lower(dest);
+
+ result->is_expr = true;
+ result->expr = expr;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : dest = désignation de la variable de destination. *
+* func = nom de la fonction assurant le calcul de valeur. *
+* args = argument(s) à fournir à cette fonction. *
+* *
+* Description : Définit une conversion à partir d'une function à appeler. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args)
+{
+ conv_func *result; /* Conversion à retourner */
+
+ result = (conv_func *)calloc(1, sizeof(conv_func));
+
+ result->dest = make_string_lower(dest);
+
+ result->is_expr = false;
+ result->name = func;
+ result->args = args;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = éléments de conversion à supprimer de la mémoire. *
+* *
+* Description : Libère de la mémoire une conversion enregistrée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_conv_func(conv_func *func)
+{
+ if (func->is_expr)
+ delete_conv_expr(func->expr);
+
+ else
+ {
+ free(func->name);
+ delete_conv_arg_list(func->args);
+ }
+
+ free(func);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à consulter. *
+* *
+* Description : Indique la variable de destination d'une conversion. *
+* *
+* Retour : Désignation humaine de la variable de destination. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *get_conv_dest_name(const conv_func *func)
+{
+ return func->dest;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à consulter. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* size = taille déterminée avec précision. [OUT] *
+* *
+* Description : Détermine la taille en bits du résultat d'une fonction. *
+* *
+* Retour : true si la taille a pu être déterminée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size)
+{
+ bool result; /* Bilan à retourner */
+
+ result = func->is_expr;
+
+ if (result)
+ result = compute_conv_expr_size(func->expr, bits, list, size);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à manipuler. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Marque les champs utilisés par une fonction de conversion. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool mark_conv_func(conv_func *func, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à remonter */
+
+ if (func->is_expr)
+ result = ensure_conv_expr_content_fully_marked(func->expr, bits, list);
+ else
+ result = ensure_arg_list_content_fully_marked(func->args, bits, list);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à manipuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : Déclare les variables associées à une fonction de conversion.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool result; /* Bilan à remonter */
+
+ /* Si la fonction a déjà été définie lors d'un précédent besoin... */
+ if (func->declared) return true;
+
+ if (func->is_expr)
+ result = ensure_conv_expr_content_fully_declared(func->expr, fd, bits, list, wide);
+ else
+ result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, wide);
+
+ func->declared = result;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à manipuler. *
+* last = précise si la conversion est la dernière. *
+* internal = indique le type de manipulation finale. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : Définit les variables associées à une fonction de conversion.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ bool result; /* Bilan à remonter */
+ const char *callable; /* Fonction à appeler */
+ regex_t preg; /* Expression régulière */
+ int ret; /* Bilan d'une manipulation */
+ regmatch_t pmatch[3]; /* Correspondances de chaînes */
+ size_t cmplen; /* Taille de comparaison */
+ char *cast; /* Macro de transtypage */
+
+ /* Si la fonction a déjà été définie lors d'un précédent besoin... */
+ if (func->defined) return true;
+
+ if (func->is_expr)
+ result = ensure_conv_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp);
+ else
+ result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp);
+
+ /* Nom de la fonction effectivement appelée */
+
+ if (!func->is_expr)
+ {
+ callable = find_macro(pp, func->name);
+
+ if (callable == NULL)
+ callable = func->name;
+
+ }
+ else callable = NULL;
+
+ if (last && callable == NULL)
+ {
+ fprintf(stderr, "Error: expected function to store '%s'.\n", func->dest);
+ return false;
+ }
+
+ /* Dernier niveau : la variable de destination est imposée ! */
+ if (last)
+ {
+ /* Si l'on doit manipuler une propriété d'instructon... */
+ if (internal)
+ {
+ ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
+ if (ret != 0)
+ {
+ fprintf(stderr, "Internal error: bad regular expression.\n");
+ return false;
+ }
+
+ ret = regexec(&preg, callable, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
+ if (ret == REG_NOMATCH)
+ {
+ fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callable);
+ result = false;
+ goto dcf_skip_internal;
+ }
+
+ /**
+ * La variable de résultat est de type 'GArchInstruction',
+ * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
+ */
+
+ cmplen = MAX(strlen(arch), pmatch[2].rm_eo - pmatch[2].rm_so);
+
+ if (strncmp("arch", &callable[pmatch[2].rm_so], cmplen) == 0)
+ dprintf(fd, "\t\tif (!%s(instr, ", callable);
+
+ else
+ {
+ cast = strndup(&callable[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+
+ cast = make_string_upper(cast);
+
+ dprintf(fd, "\t\tif (!%s(%s(instr), ", callable, cast);
+
+ free(cast);
+
+ }
+
+ result &= define_arg_list(func->args, fd, bits, list);
+
+ dprintf(fd, "))\n");
+
+ dcf_skip_internal:
+
+ regfree(&preg);
+
+ }
+
+ /* Si on doit constituer un opérande à ajouter... */
+ else
+ {
+ if (strchr(callable, '(') == NULL)
+ dprintf(fd, "\t\top = %s(", callable);
+ else
+ dprintf(fd, "\t\top = %s", callable);
+
+ result &= define_arg_list(func->args, fd, bits, list);
+
+ dprintf(fd, ");\n");
+
+ }
+
+ }
+
+ /* On constitue une variable intermédiaire, dont on peut conserver le nom ! */
+ else
+ {
+ dprintf(fd, "\t\tval_%s = ", func->dest);
+
+ if (func->is_expr)
+ result &= define_conv_expr(func->expr, fd, bits, list);
+
+ else
+ {
+ dprintf(fd, "%s(", callable);
+
+ result = define_arg_list(func->args, fd, bits, list);
+
+ dprintf(fd, ")");
+
+ }
+
+ dprintf(fd, ";\n");
+
+ }
+
+ func->defined = result;
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ENSEMBLES DE CONVERSIONS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouvelle liste vierge de fonctions de conversion. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_list *create_conv_list(void)
+{
+ conv_list *result; /* Définition vierge à renvoyer*/
+
+ result = (conv_list *)calloc(1, sizeof(conv_list));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble de fonctions de conversion à supprimer. *
+* *
+* Description : Supprime de la mémoire une de fonctions de conversion. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_conv_list(conv_list *list)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < list->func_count; i++)
+ delete_conv_func(list->functions[i]);
+
+ if (list->functions != NULL)
+ free(list->functions);
+
+ free(list);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de fonctions de conversion à compléter. *
+* func = nom de la fonction assurant le calcul de valeur. *
+* *
+* Description : Enregistre une function de conversion du brut à l'utile. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_conversion(conv_list *list, conv_func *func)
+{
+ list->functions = (conv_func **)realloc(list->functions, ++list->func_count * sizeof(conv_func *));
+
+ list->functions[list->func_count - 1] = func;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste de fonctions de conversion à consulter. *
+* name = désignation humaine du champ à retrouver. *
+* *
+* Description : Recherche un résultat précis dans une liste de fonctions. *
+* *
+* Retour : Structure associée au résulat trouvé ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_func *find_named_conv_in_list(const conv_list *list, const char *name)
+{
+ conv_func *result; /* Fonction à retourner */
+ size_t i; /* Boucle de parcours */
+ const char *dest; /* Nom de variable existante */
+
+ result = NULL;
+
+ for (i = 0; i < list->func_count && result == NULL; i++)
+ {
+ dest = get_conv_dest_name(list->functions[i]);
+
+ if (strcmp(dest, name) == 0)
+ result = list->functions[i];
+
+ }
+
+ return result;
+
+}
diff --git a/tools/conv.h b/tools/conv.h
new file mode 100644
index 0000000..acf007b
--- /dev/null
+++ b/tools/conv.h
@@ -0,0 +1,160 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * conv.h - prototypes pour les substitutions de valeurs depuis un contenu binaire
+ *
+ * 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_CONV_H
+#define _TOOLS_CONV_H
+
+
+#include "bits.h"
+#include "pproc.h"
+
+
+
+
+/* Liste des fonctions de conversions présentes */
+typedef struct _conv_list conv_list;
+
+
+
+
+
+
+
+/* Types d'opérations unaires */
+typedef enum _ConvUnaryOperation
+{
+ CUO_NOT, /* NOT (booléen) */
+
+ CUO_COUNT
+
+} ConvUnaryOperation;
+
+
+
+/* Types d'opérations binaires */
+typedef enum _ConvBinaryOperation
+{
+ CBO_EOR, /* Ou exclusif (booléen) */
+
+ CBO_COUNT
+
+} ConvBinaryOperation;
+
+
+/* Représentation d'une expression de conversion */
+typedef struct _conv_expr_t conv_expr_t;
+
+
+
+/* Référence une variable en tant qu'expression de conversion. */
+conv_expr_t *build_conv_expr_from_name(char *);
+
+/* Conserve une valeur en tant qu'expression de conversion. */
+conv_expr_t *build_conv_expr_from_number(unsigned long );
+
+/* Construit une base d'expression de conversion composée. */
+conv_expr_t *build_composed_conv_expr(char *, char *);
+
+/* Etend une base d'expression de conversion composée. */
+conv_expr_t *extend_composed_conv_expr(conv_expr_t *, char *);
+
+/* Traduit une opération unaire sur expression de conversion. */
+conv_expr_t *build_unary_conv_expr(conv_expr_t *, ConvUnaryOperation);
+
+/* Traduit une opération binaire sur expression de conversion. */
+conv_expr_t *build_binary_conv_expr(conv_expr_t *, conv_expr_t *, ConvBinaryOperation);
+
+
+
+
+
+
+
+
+/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+typedef struct _conv_arg_list_t conv_arg_list_t;
+
+
+/* Crée une liste d'arguments de conversion. */
+conv_arg_list_t *build_conv_arg_list(conv_expr_t *);
+
+/* Libère la mémoire occupée par une liste d'expressions. */
+void delete_conv_arg_list(conv_arg_list_t *);
+
+/* Ajoute un élément à une liste d'arguments de conversion. */
+conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *, conv_expr_t *);
+
+
+
+
+/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */
+
+
+/* Fonction de conversion */
+typedef struct _conv_func conv_func;
+
+
+/* Définit une conversion à partir d'une simple expression. */
+conv_func *make_conv_from_expr(char *, conv_expr_t *);
+
+/* Définit une conversion à partir d'une function à appeler. */
+conv_func *make_conv_from_func(char *, char *, conv_arg_list_t *);
+
+/* Libère de la mémoire une conversion enregistrée. */
+void delete_conv_func(conv_func *);
+
+/* Indique la variable de destination d'une conversion. */
+const char *get_conv_dest_name(const conv_func *);
+
+/* Marque les champs utilisés par une fonction de conversion. */
+bool mark_conv_func(conv_func *, const coding_bits *, const conv_list *);
+
+/* Déclare les variables associées à une fonction de conversion. */
+bool declare_conv_func(conv_func *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* Définit les variables associées à une fonction de conversion. */
+bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+
+
+/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
+
+
+/* Crée un nouvelle liste vierge de fonctions de conversion. */
+conv_list *create_conv_list(void);
+
+/* Supprime de la mémoire une de fonctions de conversion. */
+void delete_conv_list(conv_list *);
+
+/* Enregistre une function de conversion du brut à l'utile. */
+void register_conversion(conv_list *, conv_func *);
+
+/* Recherche un résultat précis dans une liste de fonctions. */
+conv_func *find_named_conv_in_list(const conv_list *, const char *);
+
+
+
+#endif /* _TOOLS_CONV_H */
diff --git a/tools/d2c_gram.y b/tools/d2c_gram.y
index 6fc8fb7..5deb053 100644
--- a/tools/d2c_gram.y
+++ b/tools/d2c_gram.y
@@ -9,6 +9,7 @@
#include "coder.h"
+#include "d2c_tok.h"
extern int yylex();
@@ -17,10 +18,10 @@ extern void free_flex_memory(void);
/* Affiche un message d'erreur suite à l'analyse en échec. */
-static int d2c_error(rented_coder *coder, char *s);
+static int d2c_error(rented_coder *, char *);
/* Affiche des indications sur l'utilisation du programme. */
-static void show_usage(const char *argv0);
+static void show_usage(const char *);
%}
@@ -31,12 +32,76 @@ static void show_usage(const char *argv0);
/* Pour la définition des expressions conditionnelles... */
#include "coder.h"
+#include "conv.h"
+
struct action_tmp
{
CondActionType action;
const char *details;
};
+
+
+
+#define register_named_field_in_coder(c, n, l) \
+ ({ \
+ encoding_spec *__spec; \
+ coding_bits *__bits; \
+ __spec = get_current_encoding_spec(c); \
+ __bits = get_bits_in_encoding_spec(__spec); \
+ register_named_field_in_bits(__bits, n, l); \
+ })
+
+#define register_bit_in_coder(c, v) \
+ ({ \
+ encoding_spec *__spec; \
+ coding_bits *__bits; \
+ __spec = get_current_encoding_spec(c); \
+ __bits = get_bits_in_encoding_spec(__spec); \
+ register_bit_in_bits(__bits, v); \
+ })
+
+#define count_coder_bits(c) \
+ ({ \
+ encoding_spec *__spec; \
+ coding_bits *__bits; \
+ __spec = get_current_encoding_spec(c); \
+ __bits = get_bits_in_encoding_spec(__spec); \
+ count_coded_bits(__bits); \
+ })
+
+#define register_syntax_item_in_coder(c, n, i) \
+ ({ \
+ encoding_spec *__spec; \
+ asm_syntax *__syntax; \
+ __spec = get_current_encoding_spec(c); \
+ __syntax = get_syntax_in_encoding_spec(__spec); \
+ register_syntax_item(__syntax, n, i); \
+ })
+
+#define register_conversion_in_coder(c, f) \
+ ({ \
+ encoding_spec *__spec; \
+ conv_list *__list; \
+ __spec = get_current_encoding_spec(c); \
+ __list = get_conversions_in_encoding_spec(__spec); \
+ register_conversion(__list, f); \
+ })
+
+#define add_conditional_rule_to_coder(c, e, a, d) \
+ ({ \
+ encoding_spec *__spec; \
+ decoding_rules *__rules; \
+ __spec = get_current_encoding_spec(c); \
+ __rules = get_rules_in_encoding_spec(__spec); \
+ register_conditional_rule(__rules, e, a, d); \
+ })
+
+
+
+
+
+
}
%union {
@@ -47,6 +112,13 @@ struct action_tmp
int integer;
+ conv_func *subst; /* Fonction de conversion */
+ conv_arg_list_t *conv_list; /* Liste d'arguments de conv. */
+
+ conv_expr_t *conv; /* Expression de conversion */
+ ConvUnaryOperation un_op; /* Opération unaire */
+ ConvBinaryOperation bin_op; /* Opération bianire */
+
cond_expr *expr; /* Expression de déclenchement */
struct action_tmp tmpa; /* Transfert temporaire */
@@ -68,7 +140,7 @@ struct action_tmp
%token SYNTAX OPERAND_INTERNAL OPERAND_VISIBLE
-%token CONV EQ ARG
+%token CONV EQ OP COMMA CP NOT EOR COLON
%token RULES IF EXPR_START EQUAL BINVAL EXPR_END AND THEN SEE
@@ -83,7 +155,13 @@ struct action_tmp
%type <string> OPERAND_INTERNAL OPERAND_VISIBLE
-%type <string> ARG
+
+%type <subst> substitution
+%type <conv_list> conv_arg_list
+%type <conv> conv_expr conv_arg_composed
+%type <un_op> conv_expr_un_op
+%type <bin_op> conv_expr_bin_op
+%type <string> conv_arg_field
%type <expr> rule_cond
%type <string> BINVAL
@@ -115,8 +193,20 @@ content : /* empty */
| rules content
-bitfield : HALF bits { if (count_coder_bits(coder) != 16) YYABORT; }
- | WORD bits { if (count_coder_bits(coder) != 32) YYABORT; }
+bitfield : HALF bits {
+ if (count_coder_bits(coder) != 16)
+ {
+ fprintf(stderr, "Unexpected word size: %u vs 16\n", count_coder_bits(coder));
+ YYABORT;
+ }
+ }
+ | WORD bits {
+ if (count_coder_bits(coder) != 32)
+ {
+ fprintf(stderr, "Unexpected word size: %u vs 32\n", count_coder_bits(coder));
+ YYABORT;
+ }
+ }
bits : /* empty */
| NAME SIZE bits { register_named_field_in_coder(coder, $1, $2); }
@@ -133,7 +223,30 @@ operands : /* empty */
conversions : CONV substitutions
substitutions : /* empty */
- | substitutions NAME EQ NAME ARG { register_conversion_in_coder(coder, $2, $4, $5); }
+ | substitutions substitution { register_conversion_in_coder(coder, $2); }
+
+substitution : NAME EQ conv_expr { $$ = make_conv_from_expr($1, $3); }
+ | NAME EQ NAME OP conv_arg_list CP { $$ = make_conv_from_func($1, $3, $5); }
+
+conv_arg_list : conv_expr { $$ = build_conv_arg_list($1); }
+ | conv_arg_list COMMA conv_expr { $$ = extend_conv_arg_list($1, $3); printf("extend\n"); }
+
+conv_expr : NAME { $$ = build_conv_expr_from_name($1); }
+ | NUMBER { $$ = build_conv_expr_from_number($1); }
+ | conv_arg_composed { $$ = $1; }
+ | OP conv_expr CP { $$ = $2; }
+ | conv_expr_un_op conv_expr { $$ = build_unary_conv_expr($2, $1); }
+ | OP conv_expr conv_expr_bin_op conv_expr CP { $$ = build_binary_conv_expr($2, $4, $3); }
+
+conv_expr_un_op : NOT { $$ = CUO_NOT; }
+
+conv_expr_bin_op : EOR { $$ = CBO_EOR; }
+
+conv_arg_composed : conv_arg_field COLON conv_arg_field { $$ = build_composed_conv_expr($1, $3); }
+ | conv_arg_composed COLON conv_arg_field { $$ = extend_composed_conv_expr($1, $3); }
+
+conv_arg_field : NAME { $$ = $1; printf(" composed::name '%s'\n", $1); }
+ | BINVAL { $$ = $1; printf(" composed::bin '%s'\n", $1); }
rules : RULES rules_list
@@ -169,7 +282,7 @@ action : SEE INS_DETAILS { $$.action = CAT_SEE; $$.details = $2; }
static int d2c_error(rented_coder *coder, char *msg)
{
- printf("yyerror : %s\n", msg);
+ printf("yyerror line %d: %s\n", d2c_get_lineno(), msg);
return 0;
@@ -287,7 +400,7 @@ int main(int argc, char **argv)
if (!has_error)
{
*sep = '\0';
- register_encoding_in_coder(coder, optarg, sep + 1);
+ register_encoding(get_coder_pre_proc(coder), optarg, sep + 1);
}
break;
@@ -300,7 +413,7 @@ int main(int argc, char **argv)
if (!has_error)
{
*sep = '\0';
- define_macro_for_coder(coder, optarg, sep + 1);
+ define_macro(get_coder_pre_proc(coder), optarg, sep + 1);
}
break;
diff --git a/tools/d2c_tok.l b/tools/d2c_tok.l
index ae4faa3..50a8d8f 100644
--- a/tools/d2c_tok.l
+++ b/tools/d2c_tok.l
@@ -19,6 +19,7 @@ void free_flex_memory(void) ;
%option noyywrap
%option nounput
%option noinput
+%option yylineno
%x comments
@@ -30,7 +31,7 @@ void free_flex_memory(void) ;
%x syntax syntax_int syntax_ext
-%x conv_begin conv_content conv_arg
+%x conv_begin conv_content conv_arg conv_arg_binval
%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_actin_see
@@ -51,7 +52,7 @@ void free_flex_memory(void) ;
"@title" { BEGIN(ins_name); return TITLE; }
<ins_name>[ ][A-Za-z-]+ { d2c_lval.string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
-<try_details>[ ] { BEGIN(ins_details); }
+<try_details>[ ,/] { BEGIN(ins_details); }
<try_details>[\n] { BEGIN(INITIAL); }
<ins_details>[^\n]* { d2c_lval.cstring = yytext; return INS_DETAILS; }
@@ -111,12 +112,33 @@ void free_flex_memory(void) ;
<conv_content>"}" { BEGIN(encoding_content); }
<conv_content>[ \t\n]+ { }
-<conv_content>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
+<conv_content>[A-Za-z][A-Za-z0-9]* {
+ if (strcmp(yytext, "NOT") == 0) return NOT;
+ else
+ {
+ d2c_lval.string = strdup(yytext);
+ return NAME;
+ }
+ }
<conv_content>"=" { return EQ; }
-
-<conv_content>"(" { BEGIN(conv_arg); }
-<conv_arg>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return ARG; }
-<conv_arg>")" { BEGIN(conv_content); }
+<conv_content>"(" { BEGIN(conv_arg); return OP; }
+<conv_arg>[A-Za-z][A-Za-z0-9]* {
+ if (strcmp(yytext, "NOT") == 0) return NOT;
+ else if (strcmp(yytext, "EOR") == 0) return EOR;
+ else
+ {
+ d2c_lval.string = strdup(yytext);
+ return NAME;
+ }
+ }
+<conv_arg>[0-9][0-9]* { d2c_lval.integer = atoi(yytext); return NUMBER; }
+<conv_arg>"'" { BEGIN(conv_arg_binval); }
+<conv_arg_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; }
+<conv_arg_binval>"'" { BEGIN(conv_arg); }
+<conv_arg>"," { return COMMA; }
+<conv_arg>":" { return COLON; }
+<conv_arg>[ ]+ { }
+<conv_arg>")" { BEGIN(conv_content); return CP; }
diff --git a/tools/helpers.c b/tools/helpers.c
new file mode 100644
index 0000000..1353ba2
--- /dev/null
+++ b/tools/helpers.c
@@ -0,0 +1,144 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers.c - fonctionnalités d'assitance à la compilation
+ *
+ * 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 "helpers.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATIONS DE CHAINES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : str = chaîne de caractères à manipuler. [OUT] *
+* *
+* Description : Bascule toute une chaîne de caractères en (min|maj)uscules. *
+* *
+* Retour : Pointeur sur la chaîne fournie. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *_make_string_xxx(char *str, int (* fn) (int))
+{
+ size_t max; /* Empleur du parcours */
+ size_t i; /* Boucle de parcours */
+
+ max = strlen(str);
+
+ for (i = 0; i < max; i++)
+ str[i] = fn(str[i]);
+
+ return str;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : raw = données brutes en provenance de l'analyseur. *
+* details = indique la nature de la chaîne à traiter. *
+* *
+* Description : Traduit une chaîne en élément de fonction C. *
+* *
+* Retour : Chaîne à libérer de la mémoire après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *make_callable(const char *raw, bool details)
+{
+ char *result; /* Nom formaté à retourner */
+ size_t max; /* Empleur du parcours */
+ size_t i; /* Boucle de parcours */
+
+ result = strdup(raw);
+
+ max = strlen(result);
+
+ /* Première passe : on vire les virgules */
+
+ for (i = 0; i < max; i++)
+ if (result[i] == ',')
+ {
+ memmove(result + i, result + i + 1, max - i - 1);
+ max--;
+ }
+
+ result[max] = '\0';
+
+ /* Deuxième passe : on bascule en minuscules */
+
+ result = make_string_lower(result);
+
+ /* Troisième passe : on remplace les mauvais caractères */
+
+ for (i = 0; i < max; i++)
+ switch (result[i])
+ {
+ case 'a' ... 'z':
+ case '0' ... '9':
+ break;
+ case '-':
+ result[i] = '_';
+ break;
+ default:
+ result[i] = (i + 1 == max ? '\0' : '_');
+ break;
+ }
+
+ /**
+ * Dernière passe : on s'assure que le premier caractère n'est pas une lettre.
+ * On ajoute ici le préfixe '_' utilisé lors de la génération de prototypes ;
+ * en cas d'absence de détails, on ne se retrouve ainsi pas avec un '_' isolé.
+ */
+
+ if (details && result[0] != '_')
+ {
+ max = strlen(result) + 1;
+ result = (char *)realloc(result, max);
+ memmove(result + 1, result, max - 1);
+ result[0] = '_';
+ }
+
+ /* Ultime passe : supression des '_' groupés */
+
+ for (i = 0; i < max; i++)
+ if (result[i] == '_' && result[i + 1] == '_')
+ {
+ memmove(result + i + 1, result + i + 2, max - i - 1);
+ max--;
+ i--;
+ }
+
+ return result;
+
+}
diff --git a/tools/helpers.h b/tools/helpers.h
new file mode 100644
index 0000000..8c39a85
--- /dev/null
+++ b/tools/helpers.h
@@ -0,0 +1,47 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers.h - prototypes pour les fonctionnalités d'assitance à la compilation
+ *
+ * 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_HELPERS_H
+#define _TOOLS_HELPERS_H
+
+
+#include <ctype.h>
+#include <stdbool.h>
+
+
+
+/* ---------------------------- MANIPULATIONS DE CHAINES ---------------------------- */
+
+
+/* Bascule toute une chaîne de caractères en (min|maj)uscules. */
+char *_make_string_xxx(char *, int (* fn) (int));
+
+#define make_string_lower(str) _make_string_xxx(str, tolower)
+#define make_string_upper(str) _make_string_xxx(str, toupper)
+
+/* Traduit une chaîne en élément de fonction C. */
+char *make_callable(const char *raw, bool);
+
+
+
+#endif /* _TOOLS_HELPERS_H */
diff --git a/tools/macros.c b/tools/macros.c
new file mode 100644
index 0000000..b1c44f0
--- /dev/null
+++ b/tools/macros.c
@@ -0,0 +1,167 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pproc.c - remplacements à la volée de chaînes de caractères
+ *
+ * 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 "pproc.h"
+
+
+#include <malloc.h>
+
+
+
+
+
+
+/* Conversion des chaînes en chaînes */
+typedef struct _string_exch
+{
+ const char *src; /* Chaîne à trouver */
+ const char *dest; /* Chaîne de remplacement */
+
+} string_exch;
+
+
+/* Pré-processeur avec support des macros */
+struct _pre_processor
+{
+ string_exch *macros; /* Remplacements de chaînes */
+ size_t macros_count; /* Nombre de ces remplacements */
+
+
+
+}
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau suivi de l'encodage d'une instruction. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+encoding_spec *create_encoding_spec(void)
+{
+ encoding_spec *result; /* Définition vierge à renvoyer*/
+
+ result = (encoding_spec *)calloc(1, sizeof(encoding_spec));
+
+ result->bits = create_coding_bits();
+ result->syntax = create_asm_syntax();
+ result->conversions = create_conv_list();
+ result->rules = create_decoding_rules();
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à libérer de la mémoire. *
+* *
+* Description : Supprime de la mémoire un suivi d'encodage d'une instruction.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_encoding_spec(encoding_spec *spec)
+{
+ delete_coding_bits(spec->bits);
+ delete_asm_syntax(spec->syntax);
+ delete_conv_list(spec->conversions);
+ delete_decoding_rules(spec->rules);
+
+ free(spec);
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* src = chaîne à remplacer dans les définitions. *
+* dest = chaîne de remplacement. *
+* *
+* Description : Constitue la matière d'un système de macros. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void define_macro_for_coder(rented_coder *coder, const char *src, const char *dest)
+{
+ string_exch *macro; /* Nouvelle macro à constituer */
+
+ coder->macros = (string_exch *)realloc(coder->macros, ++coder->macros_count * sizeof(string_exch));
+
+ macro = &coder->macros[coder->macros_count - 1];
+
+ macro->src = src;
+ macro->dest = dest;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* src = chaîne à remplacer dans les définitions. *
+* *
+* Description : Recherche l'existence d'une macro pour un remplacement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static const char *find_macro_in_coder(const rented_coder *coder, const char *src)
+{
+ const char *result; /* Trouvaille à renvoyer */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < coder->macros_count && result == NULL; i++)
+ if (strcmp(coder->macros[i].src, src) == 0)
+ result = coder->macros[i].dest;
+
+ return result;
+
+}
+
+
diff --git a/tools/macros.h b/tools/macros.h
new file mode 100644
index 0000000..3755f00
--- /dev/null
+++ b/tools/macros.h
@@ -0,0 +1,30 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * macros.h - prototypes pour les remplacements à la volée de chaînes de caractères
+ *
+ * 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_MACROS_H
+#define _TOOLS_MACROS_H
+
+
+
+
+#endif /* _TOOLS_MACROS_H */
diff --git a/tools/pproc.c b/tools/pproc.c
new file mode 100644
index 0000000..8644af5
--- /dev/null
+++ b/tools/pproc.c
@@ -0,0 +1,214 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pproc.c - remplacements à la volée de chaînes de caractères
+ *
+ * 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 "pproc.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+
+/* Pré-processeur avec support des macros */
+struct _pre_processor
+{
+ string_exch *encodings; /* Traductions d'encodages */
+ size_t encodings_count; /* Nombre de ces traductions */
+
+ string_exch *macros; /* Remplacements de chaînes */
+ size_t macros_count; /* Nombre de ces remplacements */
+
+};
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau pre-processeur pour le support des macros. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+pre_processor *create_pre_processor(void)
+{
+ pre_processor *result; /* Définition vierge à renvoyer*/
+
+ result = (pre_processor *)calloc(1, sizeof(pre_processor));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur à libérer de la mémoire. *
+* *
+* Description : Supprime de la mémoire un pré-processeur et ses macros. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_pre_processor(pre_processor *pp)
+{
+ if (pp->encodings != NULL)
+ free(pp->encodings);
+
+ if (pp->macros != NULL)
+ free(pp->macros);
+
+ free(pp);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
+* src = chaîne à remplacer dans les définitions. *
+* dest = chaîne de remplacement. *
+* *
+* Description : Enregistre une correspondance en matière d'encodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_encoding(pre_processor *pp, const char *src, const char *dest)
+{
+ 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 = src;
+ encoding->dest = dest;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
+* *
+* Description : Indique le nombre de catégories d'encodages enregistrées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t count_encodings(const pre_processor *pp)
+{
+ return pp->encodings_count;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
+* index = indice de l'encodage à retourner. *
+* *
+* Description : Fournit une catégorie d'encodage donnée. *
+* *
+* Retour : Correspondance à consulter uniquement. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const string_exch *find_encoding(const pre_processor *pp, size_t index)
+{
+ return &pp->encodings[index];
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur dont le contenu est à compléter. *
+* src = chaîne à remplacer dans les définitions. *
+* dest = chaîne de remplacement. *
+* *
+* Description : Constitue la matière d'un système de macros. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void define_macro(pre_processor *pp, const char *src, const char *dest)
+{
+ string_exch *macro; /* Nouvelle macro à constituer */
+
+ pp->macros = (string_exch *)realloc(pp->macros, ++pp->macros_count * sizeof(string_exch));
+
+ macro = &pp->macros[pp->macros_count - 1];
+
+ macro->src = src;
+ macro->dest = dest;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : pp = pré-processeur dont le contenu est à consulter. *
+* src = chaîne à remplacer dans les définitions. *
+* *
+* Description : Recherche l'existence d'une macro pour un remplacement. *
+* *
+* Retour : Eventuelle correspondance trouvée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *find_macro(const pre_processor *pp, const char *src)
+{
+ const char *result; /* Trouvaille à renvoyer */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ for (i = 0; i < pp->macros_count && result == NULL; i++)
+ if (strcmp(pp->macros[i].src, src) == 0)
+ result = pp->macros[i].dest;
+
+ return result;
+
+}
diff --git a/tools/pproc.h b/tools/pproc.h
new file mode 100644
index 0000000..6675fa1
--- /dev/null
+++ b/tools/pproc.h
@@ -0,0 +1,67 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * pproc.h - prototypes pour les remplacements à la volée de chaînes de caractères
+ *
+ * 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_PPROC_H
+#define _TOOLS_PPROC_H
+
+
+#include <sys/types.h>
+
+
+
+/* Conversion des chaînes en chaînes */
+typedef struct _string_exch
+{
+ const char *src; /* Chaîne à trouver */
+ const char *dest; /* Chaîne de remplacement */
+
+} string_exch;
+
+/* Pré-processeur avec support des macros */
+typedef struct _pre_processor pre_processor;
+
+
+/* Crée un nouveau pre-processeur pour le support des macros. */
+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 en matière d'encodage. */
+void register_encoding(pre_processor *, const char *, const char *);
+
+/* Indique le nombre de catégories d'encodages enregistrées. */
+size_t count_encodings(const pre_processor *);
+
+/* Fournit une catégorie d'encodage donnée. */
+const string_exch *find_encoding(const pre_processor *, size_t);
+
+/* Constitue la matière d'un système de macros. */
+void define_macro(pre_processor *, const char *, const char *);
+
+/* Recherche l'existence d'une macro pour un remplacement. */
+const char *find_macro(const pre_processor *, const char *);
+
+
+
+#endif /* _TOOLS_PPROC_H */
diff --git a/tools/rules.c b/tools/rules.c
new file mode 100644
index 0000000..25ba76c
--- /dev/null
+++ b/tools/rules.c
@@ -0,0 +1,439 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rules.h - prototypes pour les variations de décodage selon certaines conditions
+ *
+ * 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 "rules.h"
+
+
+#include <malloc.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+#include "helpers.h"
+
+
+
+/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */
+
+
+/* Expression d'une condition */
+struct _cond_expr
+{
+ bool is_simple; /* Sélection de champ */
+
+ union
+ {
+ struct
+ {
+ char *variable; /* Variable manipulée */
+ CondCompType comp; /* Type de comparaison */
+ char *bvalue; /* Valeur binaire comparée */
+
+ } simple;
+
+ struct
+ {
+ cond_expr *a; /* Première sous-expression */
+ CondOpType operator; /* Relation entre expressions */
+ cond_expr *b; /* Seconde sous-expression */
+
+ } composed;
+
+ };
+
+};
+
+
+/* Libère de la mémoire une expression conditionnelle. */
+static void delete_cond_expr(cond_expr *);
+
+/* Traduit en code une expression de condition. */
+static bool write_cond_expr(const cond_expr *, int, const coding_bits *);
+
+
+
+/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */
+
+
+/* Règle particulière */
+typedef struct _extra_rule
+{
+ cond_expr *expr; /* Expression de déclenchement */
+ CondActionType action; /* Conséquence d'une validation*/
+ char *details; /* Eventuel complément d'info. */
+
+} extra_rule;
+
+/* Règles de décodage supplémentaires */
+struct _decoding_rules
+{
+ extra_rule *extra; /* Règles conditionnelles */
+ size_t extra_count; /* Nombre de ces règles */
+
+};
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONDITIONS DE DECLENCHEMENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : variable = désignation de la variable à manipuler. *
+* comp = type de comparaison à utiliser. *
+* bvalue = valeur binaire à comparer. *
+* *
+* Description : Crée une expression conditionnelle simple. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue)
+{
+ cond_expr *result; /* Structure à retourner */
+
+ result = (cond_expr *)calloc(1, sizeof(cond_expr));
+
+ result->is_simple = true;
+
+ result->simple.variable = make_string_lower(variable);
+ result->simple.comp = comp;
+ result->simple.bvalue = bvalue;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = première expression à intégrer. *
+* operator = type de comparaison à utiliser. *
+* b = second expression à intégrer. *
+* *
+* Description : Crée une expression conditionnelle composée. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cond_expr *build_composed_cond_expression(cond_expr *a, CondOpType operator, cond_expr *b)
+{
+ cond_expr *result; /* Structure à retourner */
+
+ result = (cond_expr *)calloc(1, sizeof(cond_expr));
+
+ result->is_simple = false;
+
+ result->composed.a = a;
+ result->composed.operator = operator;
+ result->composed.b = b;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = représentation d'expression à traiter. *
+* *
+* Description : Libère de la mémoire une expression conditionnelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_cond_expr(cond_expr *expr)
+{
+ if (expr->is_simple)
+ {
+ free(expr->simple.variable);
+ free(expr->simple.bvalue);
+ }
+ else
+ {
+ delete_cond_expr(expr->composed.a);
+ delete_cond_expr(expr->composed.b);
+ }
+
+ free(expr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression simple ou composée à transposer. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* *
+* Description : Traduit en code une expression de condition. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bits)
+{
+ bool result; /* Bilan à renvoyer */
+ const raw_bitfield *bf; /* Champ de bits de définition */
+
+ result = true;
+
+ dprintf(fd, "(");
+
+ if (expr->is_simple)
+ {
+ bf = find_named_field_in_bits(bits, expr->simple.variable);
+ if (bf == NULL)
+ {
+ fprintf(stderr, "Error: no bitfield defined the requested variable '%s'.\n", expr->simple.variable);
+ result = false;
+ goto wce_exit;
+ }
+
+ if (get_raw_bitfield_length(bf) != strlen(expr->simple.bvalue))
+ {
+ fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n",
+ expr->simple.variable, get_raw_bitfield_length(bf), strlen(expr->simple.bvalue));
+ result = false;
+ goto wce_exit;
+ }
+
+ dprintf(fd, "raw_%s", expr->simple.variable);
+
+ switch (expr->simple.comp)
+ {
+ case CCT_EQUAL:
+ dprintf(fd, " == ");
+ break;
+ case CCT_DIFF:
+ dprintf(fd, " != ");
+ break;
+ }
+
+ dprintf(fd, "b%s", expr->simple.bvalue);
+
+ }
+ else
+ {
+ result = write_cond_expr(expr->composed.a, fd, bits);
+ if (!result) goto wce_exit;
+
+ switch (expr->composed.operator)
+ {
+ case COT_AND:
+ dprintf(fd, " && ");
+ break;
+ case COT_OR:
+ dprintf(fd, " || ");
+ break;
+ }
+
+ result = write_cond_expr(expr->composed.b, fd, bits);
+ if (!result) goto wce_exit;
+
+ }
+
+ dprintf(fd, ")");
+
+ wce_exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* REGLES ET ACTIONS CONSEQUENTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau rassemblement de règles de décodage. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+decoding_rules *create_decoding_rules(void)
+{
+ decoding_rules *result; /* Définition vierge à renvoyer*/
+
+ result = (decoding_rules *)calloc(1, sizeof(decoding_rules));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles de décodage à supprimer. *
+* *
+* Description : Supprime de la mémoire un ensemble de règles supplémentaires.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_decoding_rules(decoding_rules *rules)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < rules->extra_count; i++)
+ {
+ delete_cond_expr(rules->extra[i].expr);
+ if (rules->extra[i].details)
+ free(rules->extra[i].details);
+ }
+
+ if (rules->extra != NULL)
+ free(rules->extra);
+
+ free(rules);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles à compléter. *
+* expr = représentation d'expression à conserver. *
+* action = conséquence associée à la règle. *
+* details = éventuel complément d'informations. *
+* *
+* Description : Ajoute une règle complète à la définition d'un codage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActionType action, const char *details)
+{
+ extra_rule *rule; /* Nouvelle prise en compte */
+
+ rules->extra = (extra_rule *)realloc(rules->extra, ++rules->extra_count * sizeof(extra_rule));
+
+ rule = &rules->extra[rules->extra_count - 1];
+
+ rule->expr = expr;
+ rule->action = action;
+ rule->details = (details != NULL ? make_callable(details, false) : NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles à consulter. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* exit = exprime le besoin d'une voie de sortie. [OUT] *
+* *
+* Description : Traduit en code les éventuelles règles présentes. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_decoding_rules(decoding_rules *rules, int fd, const coding_bits *bits, bool *exit)
+{
+ bool result; /* Bilan à remonter */
+ const extra_rule *rule; /* Règle en cours d'écriture */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ *exit = false;
+
+ for (i = 0; i < rules->extra_count; i++)
+ {
+ rule = &rules->extra[i];
+
+ dprintf(fd, "\t\tif ");
+
+ result = write_cond_expr(rule->expr, fd, bits);
+ if (!result) break;
+
+ dprintf(fd, "\n");
+ dprintf(fd, "\t\t{\n");
+
+ switch (rule->action)
+ {
+ case CAT_SEE:
+
+ if (rule->details == NULL)
+ {
+ fprintf(stderr, "Error: directive 'see' must provide additional details.\n");
+ result = false;
+ goto wcsr_exit;
+ }
+
+ dprintf(fd, "\t\t\tinstr = armv7_read_instr_%s", rule->details);
+
+ /* TODO : adapter les paramètres d'appel selon le 'coder' */
+ dprintf(fd, "(_raw);\n");
+
+ dprintf(fd, "\t\t\tgoto quick_exit;\n");
+
+ *exit = true;
+ break;
+
+ }
+
+ dprintf(fd, "\t\t}\n");
+
+ dprintf(fd, "\n");
+
+ }
+
+ wcsr_exit:
+
+ return result;
+
+}
diff --git a/tools/rules.h b/tools/rules.h
new file mode 100644
index 0000000..a4a9bb4
--- /dev/null
+++ b/tools/rules.h
@@ -0,0 +1,91 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * rules.h - prototypes pour les variations de décodage selon certaines conditions
+ *
+ * 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_RULES_H
+#define _TOOLS_RULES_H
+
+
+#include "bits.h"
+
+
+
+/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */
+
+
+/* Types de comparaison */
+typedef enum _CondCompType
+{
+ CCT_EQUAL, /* Egalité '==' */
+ CCT_DIFF /* Différence '!=' */
+
+} CondCompType;
+
+/* Types de combinaison d'expressions */
+typedef enum _CondOpType
+{
+ COT_AND, /* Combinaison ET ('&&') */
+ COT_OR /* Combinaison OU ('||') */
+
+} CondOpType;
+
+/* Expression d'une condition */
+typedef struct _cond_expr cond_expr;
+
+
+/* Crée une expression conditionnelle simple. */
+cond_expr *build_simple_cond_expression(char *, CondCompType, char *);
+
+/* Crée une expression conditionnelle composée. */
+cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
+
+
+
+/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */
+
+
+/* Conséquence en cas de condition remplie */
+typedef enum _CondActionType
+{
+ CAT_SEE /* Renvoi vers une instruction */
+
+} CondActionType;
+
+/* Règles de décodage supplémentaires */
+typedef struct _decoding_rules decoding_rules;
+
+
+/* Crée un nouveau rassemblement de règles de décodage. */
+decoding_rules *create_decoding_rules(void);
+
+/* Supprime de la mémoire un ensemble de règles supplémentaires. */
+void delete_decoding_rules(decoding_rules *);
+
+/* Ajoute une règle complète à la définition d'un codage. */
+void register_conditional_rule(decoding_rules *, cond_expr *, CondActionType, const char *);
+
+/* Traduit en code les éventuelles règles présentes. */
+bool write_decoding_rules(decoding_rules *, int, const coding_bits *, bool *);
+
+
+
+#endif /* _TOOLS_RULES_H */
diff --git a/tools/spec.c b/tools/spec.c
new file mode 100644
index 0000000..a957587
--- /dev/null
+++ b/tools/spec.c
@@ -0,0 +1,349 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * spec.c - représentation complète d'un encodage
+ *
+ * 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 "spec.h"
+
+
+#include <malloc.h>
+#include <regex.h>
+#include <string.h>
+
+
+#include "helpers.h"
+
+
+
+
+
+#define get_raw_bitfield_name(bf) ""
+
+
+
+
+
+#define get_syntax_item_name(si) ""
+
+
+
+
+
+
+
+/* Mémorisation d'un encodage complet */
+struct _encoding_spec
+{
+ char *prefix; /* Distinction principale */
+ unsigned int index; /* Distinction secondaire */
+
+ coding_bits *bits; /* Encodage des bits associés */
+ asm_syntax *syntax; /* Calligraphe d'assemblage */
+ conv_list *conversions; /* Conversions des données */
+ decoding_rules *rules; /* Règles supplémentaires */
+
+};
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau suivi de l'encodage d'une instruction. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+encoding_spec *create_encoding_spec(void)
+{
+ encoding_spec *result; /* Définition vierge à renvoyer*/
+
+ result = (encoding_spec *)calloc(1, sizeof(encoding_spec));
+
+ result->bits = create_coding_bits();
+ result->syntax = create_asm_syntax();
+ result->conversions = create_conv_list();
+ result->rules = create_decoding_rules();
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à libérer de la mémoire. *
+* *
+* Description : Supprime de la mémoire un suivi d'encodage d'une instruction.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_encoding_spec(encoding_spec *spec)
+{
+ delete_coding_bits(spec->bits);
+ delete_asm_syntax(spec->syntax);
+ delete_conv_list(spec->conversions);
+ delete_decoding_rules(spec->rules);
+
+ free(spec);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à compléter. *
+* prefix = distinction principale entre les définitions. *
+* index = distinction secondaire entre les définitions. *
+* *
+* Description : Définit le nom de code d'une spécification d'encodage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void define_encoding_spec_code_name(encoding_spec *spec, char *prefix, unsigned int index)
+{
+ spec->prefix = prefix;
+ spec->index = index;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à consulter. *
+* prefix = distinction principale entre les définitions. *
+* *
+* Description : Indique si une spécification se range dans une catégorie. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool has_encoding_spec_prefix(const encoding_spec *spec, const char *prefix)
+{
+ return (strcmp(spec->prefix, prefix) == 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à consulter. *
+* *
+* Description : Fournit le gestionnaire des bits d'un encodage d'instruction.*
+* *
+* Retour : Structure assurant le suivi des bits. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+coding_bits *get_bits_in_encoding_spec(const encoding_spec *spec)
+{
+ return spec->bits;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à consulter. *
+* *
+* Description : Fournit l'indicateur des écritures correctes d'assembleur. *
+* *
+* Retour : Structure assurant la gestion des éléments de syntaxe. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_syntax *get_syntax_in_encoding_spec(const encoding_spec *spec)
+{
+ return spec->syntax;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à consulter. *
+* *
+* Description : Fournit la liste des fonctions de conversion. *
+* *
+* Retour : Structure assurant la gestion des fonctions de conversion. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+conv_list *get_conversions_in_encoding_spec(const encoding_spec *spec)
+{
+ return spec->conversions;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : spec = spécification d'encodage à consulter. *
+* *
+* Description : Fournit un ensemble de règles supplémentaires éventuel. *
+* *
+* Retour : Structure assurant la gestion de ces règles. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+decoding_rules *get_rules_in_encoding_spec(const encoding_spec *spec)
+{
+ return spec->rules;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* 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. *
+* *
+* Description : Traduit en code une sous-fonction de désassemblage. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *arch, const char *ins, const char *details, unsigned int wide, const pre_processor *pp)
+{
+ bool result; /* Bilan à retourner */
+ char *keyword; /* Mot clef appelable en code */
+ bool exit; /* Inclusion de sortie rapide ?*/
+
+ result = true;
+
+ keyword = make_callable(ins, false);
+
+ dprintf(fd, "\tGArchInstruction *%s_decode_%s%s_%s%u(uint%u_t _raw)\n",
+ arch, keyword, details, spec->prefix, spec->index, wide);
+
+ dprintf(fd, "\t{\n");
+
+ dprintf(fd, "\t\tGArchInstruction *instr;\n");
+
+ /* Déclaration des champs à retrouver */
+
+ result &= mark_syntax_items(spec->syntax, spec->bits, spec->conversions);
+
+ result &= declare_used_bits_fields(spec->bits, fd, wide);
+
+ result &= declare_syntax_items(spec->syntax, fd, spec->bits, spec->conversions, wide);
+
+ dprintf(fd, "\n");
+
+ /* Vérification que le décodage est possible */
+
+ result &= check_bits_correctness(spec->bits, fd);
+
+ dprintf(fd, "\n");
+
+ /* Définition des champs bruts */
+
+ result &= define_used_bits_fields(spec->bits, fd);
+
+ dprintf(fd, "\n");
+
+ /* Inclusion des éventuelles règles */
+
+ result &= write_decoding_rules(spec->rules, fd, spec->bits, &exit);
+
+ /* Création de l'instruction en elle-même */
+
+ dprintf(fd, "\t\tinstr = g_%s_instruction_new(\"%s\");\n", arch, ins);
+
+ dprintf(fd, "\n");
+
+ /* Création des opérandes */
+
+ result &= define_syntax_items(spec->syntax, fd, arch, spec->bits, spec->conversions, pp);
+
+ /* Conclusion de la procédure */
+
+ if (exit)
+ {
+ dprintf(fd, "\t quick_exit:\n");
+ dprintf(fd, "\n");
+ }
+
+ dprintf(fd, "\t\treturn instr;\n");
+
+ dprintf(fd, "\n");
+
+ dprintf(fd, "\t bad_exit:\n");
+
+ dprintf(fd, "\n");
+
+ dprintf(fd, "\t\tg_object_unref(G_OBJECT(instr));\n");
+ dprintf(fd, "\t\treturn NULL;\n");
+
+ dprintf(fd, "\n");
+
+ dprintf(fd, "\t}\n");
+
+ dprintf(fd, "\n");
+
+ dprintf(fd, "\tif (result == NULL)\n");
+ dprintf(fd, "\t\tresult = %s_decode_%s%s_%s%u(raw);\n",
+ arch, keyword, details, spec->prefix, spec->index);
+
+ dprintf(fd, "\n");
+
+ free(keyword);
+
+ return result;
+
+}
diff --git a/tools/spec.h b/tools/spec.h
new file mode 100644
index 0000000..46d922b
--- /dev/null
+++ b/tools/spec.h
@@ -0,0 +1,72 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * spec.h - prototypes pour la représentation complète d'un encodage
+ *
+ * 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_SPEC_H
+#define _TOOLS_SPEC_H
+
+
+#include <stdbool.h>
+
+
+#include "bits.h"
+#include "conv.h"
+#include "pproc.h"
+#include "rules.h"
+#include "syntax.h"
+
+
+
+/* Mémorisation d'un encodage complet */
+typedef struct _encoding_spec encoding_spec;
+
+
+/* Crée un nouveau suivi de l'encodage d'une instruction. */
+encoding_spec *create_encoding_spec(void);
+
+/* Supprime de la mémoire un suivi d'encodage d'une instruction. */
+void delete_encoding_spec(encoding_spec *);
+
+/* Définit le nom de code d'une spécification d'encodage. */
+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 bits d'un encodage d'instruction. */
+coding_bits *get_bits_in_encoding_spec(const encoding_spec *);
+
+/* Fournit l'indicateur des écritures correctes d'assembleur. */
+asm_syntax *get_syntax_in_encoding_spec(const encoding_spec *);
+
+/* Fournit la liste des fonctions de conversion. */
+conv_list *get_conversions_in_encoding_spec(const encoding_spec *);
+
+/* Fournit un ensemble de règles supplémentaires éventuel. */
+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 *, unsigned int, const pre_processor *);
+
+
+
+#endif /* _TOOLS_SPEC_H */
diff --git a/tools/syntax.c b/tools/syntax.c
new file mode 100644
index 0000000..5fec1a6
--- /dev/null
+++ b/tools/syntax.c
@@ -0,0 +1,321 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * syntax.c - prise en compte d'une syntaxe du langage d'assemblage
+ *
+ * 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 "syntax.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "helpers.h"
+
+
+
+/* Propriétés particulières pour les opérandes */
+typedef enum _SyntaxItemFlags
+{
+ SIF_NONE = (0 << 0), /* Aucune propriété */
+ SIF_DECIMAL = (1 << 0) /* Affichage en décimal */
+
+} SyntaxItemFlags;
+
+/* Elément défini dans une syntaxe */
+typedef struct _syntax_item
+{
+ char *name; /* Désignation humaine */
+ bool internal; /* Enregistrement générique ? */
+ SyntaxItemFlags flags; /* Propriétés supplémentaires */
+
+} syntax_item;
+
+/* Syntaxe d'une ligne d'assembleur */
+struct _asm_syntax
+{
+ syntax_item *items; /* Eléments de la syntaxe */
+ size_t items_count; /* Nombre de ces éléments */
+
+};
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouvel indicateur pour l'écriture d'une instruction. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+asm_syntax *create_asm_syntax(void)
+{
+ asm_syntax *result; /* Définition vierge à renvoyer*/
+
+ result = (asm_syntax *)calloc(1, sizeof(asm_syntax));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. *
+* *
+* Description : Supprime de la mémoire un indicateur d'écriture ASM. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_asm_syntax(asm_syntax *syntax)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < syntax->items_count; i++)
+ free(syntax->items[i].name);
+
+ if (syntax->items != NULL)
+ free(syntax->items);
+
+ free(syntax);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. *
+* name = désignation de l'opérande dans la spécification. *
+* internal = précise si l'opérand est non générique ou non. *
+* *
+* Description : Enregistre la présence d'un nouvel opérande dans la syntaxe. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_syntax_item(asm_syntax *syntax, char *name, bool internal)
+{
+ syntax_item *item; /* Nouvelle prise en compte */
+ size_t len; /* Taille du nom fourni */
+
+ syntax->items = (syntax_item *)realloc(syntax->items, ++syntax->items_count * sizeof(syntax_item));
+
+ item = &syntax->items[syntax->items_count - 1];
+
+ /* Récupération des drapeaux */
+
+ item->flags = SIF_NONE;
+
+ for (len = strlen(name); len > 0; len--)
+ switch (name[0])
+ {
+ case '#':
+ item->flags |= SIF_DECIMAL;
+ memmove(name, name + 1, len);
+ break;
+
+ default:
+ len = 1;
+ break;
+
+ }
+
+ item->name = make_string_lower(name);
+ item->internal = internal;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Marque les champs de bits effectivement utilisés. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool mark_syntax_items(const asm_syntax *syntax, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ syntax_item *item; /* Lien vers un opérande */
+ conv_func *func; /* Fonction de conversion */
+
+ result = true;
+
+ for (i = 0; i < syntax->items_count && result; i++)
+ {
+ item = &syntax->items[i];
+
+ func = find_named_conv_in_list(list, item->name);
+ if (func == NULL)
+ {
+ fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name);
+ result = false;
+ }
+
+ result = mark_conv_func(func, bits, list);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : Déclare les variables C associées aux opérandes de syntaxe. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool declare_syntax_items(const asm_syntax *syntax, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool result; /* Bilan à retourner */
+ bool has_operand; /* Présence d'un opérande */
+ size_t i; /* Boucle de parcours */
+ syntax_item *item; /* Lien vers un opérande */
+ conv_func *func; /* Fonction de conversion */
+
+ result = true;
+
+ has_operand = false;
+
+ for (i = 0; i < syntax->items_count && result; i++)
+ {
+ item = &syntax->items[i];
+
+ has_operand |= !item->internal;
+
+ func = find_named_conv_in_list(list, item->name);
+ if (func == NULL)
+ {
+ fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name);
+ result = false;
+ }
+
+ result &= declare_conv_func(func, fd, bits, list, wide);
+
+ }
+
+ if (has_operand)
+ dprintf(fd, "\t\tGArchOperand *op;\n");
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = gestionnaire d'un ensemble d'éléments de syntaxe. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : Définit les variables C associées aux opérandes de syntaxe. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_syntax_items(const asm_syntax *syntax, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+ syntax_item *item; /* Lien vers un opérande */
+ conv_func *func; /* Fonction de conversion */
+
+ result = true;
+
+ for (i = 0; i < syntax->items_count && result; i++)
+ {
+ item = &syntax->items[i];
+
+ func = find_named_conv_in_list(list, item->name);
+ if (func == NULL)
+ {
+ fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name);
+ result = false;
+ }
+
+ /* Appel proprement dit */
+
+ result &= define_conv_func(func, true, item->internal, fd, arch, bits, list, pp);
+ if (!result) break;
+
+ /* Raccordement : propriété ou opérande ? */
+
+ if (item->internal)
+ dprintf(fd, "\t\t\tgoto bad_exit;\n");
+
+ else
+ {
+ dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n");
+
+ dprintf(fd, "\n");
+
+ if (item->flags & SIF_DECIMAL)
+ dprintf(fd, "\t\tg_imm_operand_set_display(G_IMM_OPERAND(op), IOD_DEC);\n");
+
+ dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n");
+
+ }
+
+ dprintf(fd, "\n");
+
+ }
+
+ return result;
+
+}
diff --git a/tools/syntax.h b/tools/syntax.h
new file mode 100644
index 0000000..0cd9210
--- /dev/null
+++ b/tools/syntax.h
@@ -0,0 +1,61 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * syntax.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage
+ *
+ * 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_SYNTAX_H
+#define _TOOLS_SYNTAX_H
+
+
+#include <stdbool.h>
+
+
+#include "bits.h"
+#include "conv.h"
+#include "pproc.h"
+
+
+
+/* Syntaxe d'une ligne d'assembleur */
+typedef struct _asm_syntax asm_syntax;
+
+
+/* Crée un nouvel indicateur pour l'écriture d'une instruction. */
+asm_syntax *create_asm_syntax(void);
+
+/* Supprime de la mémoire un indicateur d'écriture ASM. */
+void delete_asm_syntax(asm_syntax *);
+
+/* Enregistre la présence d'un nouvel opérande dans la syntaxe. */
+void register_syntax_item(asm_syntax *, char *, bool);
+
+/* Marque les champs de bits effectivement utilisés. */
+bool mark_syntax_items(const asm_syntax *, const coding_bits *, const conv_list *);
+
+/* Déclare les variables C associées aux opérandes de syntaxe. */
+bool declare_syntax_items(const asm_syntax *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* Définit les variables C associées aux opérandes de syntaxe. */
+bool define_syntax_items(const asm_syntax *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+
+
+#endif /* _TOOLS_SYNTAX_H */