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