summaryrefslogtreecommitdiff
path: root/tools/d2c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/d2c')
-rw-r--r--tools/d2c/coder.c519
-rw-r--r--tools/d2c/coder.h3
-rw-r--r--tools/d2c/d2c.mk8
-rw-r--r--tools/d2c/d2c_genmakefile.sh187
-rw-r--r--tools/d2c/d2c_gram.y7
-rw-r--r--tools/d2c/globalgen.mk12
6 files changed, 603 insertions, 133 deletions
diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c
index b4bf21f..c709bcf 100644
--- a/tools/d2c/coder.c
+++ b/tools/d2c/coder.c
@@ -32,6 +32,8 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include "helpers.h"
@@ -41,12 +43,10 @@
/* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */
-
-
-
/* Suivi des constructions */
struct _rented_coder
{
+ const char *input; /* Fichier de définitions */
const char *outdir; /* Lieu d'enregistrement */
const char *arch; /* Architecture à traiter */
const char *header; /* En-tête pour les en-têtes */
@@ -65,50 +65,26 @@ struct _rented_coder
+/* --------------------------- GENERATIONS DE CODE SOURCE --------------------------- */
-/* --------------------------- REPRESENTATION D'ENCODAGES --------------------------- */
-
-
-
-
-
-/* --------------------------- GESTION DES CHAMPS DE BITS --------------------------- */
-
-
-/* Elément d'un mot décodé */
-typedef struct _dec_bitfield
-{
- char *name; /* Désignation humaine */
- unsigned int start; /* Position de départ */
- unsigned int length; /* Taille du champ */
-
-} dec_bitfield;
-
-
-
-
-
-
-
-/* ---------------------------- CONVERSION DES ARGUMENTS ---------------------------- */
-
-
-/* Fonction de conversion */
-typedef struct _conv_func
-{
- char *dest; /* Variable de destination */
- char *func; /* Fonction de conversion */
- char *arg; /* Argument de cette fonction */
-} conv_func;
+/* S'assure de la présence du répertoire de sortie du code. */
+static bool check_gen_dir(const rented_coder *);
+/* Imprime dans un flux donné un commentaire de propriété. */
+static void write_owner_comments(const rented_coder *, int, const char *, const char *, char);
+/* Construit un chemin d'accès à un modèle de fichier de code. */
+static char *build_template_filename(const rented_coder *, const char *, const char *, char);
-/* --------------------------- GENERATIONS DE CODE SOURCE --------------------------- */
+/* Définit un modèle d'en-tête de définitions. */
+static bool create_template_file(const rented_coder *, const char *, const char *, char);
+/* Construit un chemin d'accès à un fichier de code source. */
+static char *build_code_filename(const rented_coder *, const char *, const char *, const char *, char);
/* Ouvre un fichier en écriture pour y placer du code. */
-static int create_code_file(const rented_coder *, const char *, const char *, const char *, char, bool *);
+static int create_code_file(const rented_coder *, const char *, const char *, const char *, char);
/* 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);
@@ -206,6 +182,26 @@ bool do_basic_checks_with_coder(const rented_coder *coder)
/******************************************************************************
* *
* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* outdir = fichier de définitions à venir lire. *
+* *
+* Description : Spécifie le fichier de définition à prendre en entrée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void set_coder_input_file(rented_coder *coder, const char *input)
+{
+ coder->input = input;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
* outdir = répertoire de génération des fichiers. *
* *
* Description : Spécifie le répertoire de base pour les sorties de code. *
@@ -370,67 +366,273 @@ void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index)
/******************************************************************************
* *
* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* dir = répertoire final de destination. *
+* *
+* Description : S'assure de la présence du répertoire de sortie du code. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool check_gen_dir(const rented_coder *coder)
+{
+ bool has_gen; /* Répertoire de sortie présent*/
+ int ret; /* Bilan d'un appel externe */
+
+ has_gen = (access(".gen", F_OK) == 0);
+
+ if (has_gen)
+ {
+ ret = access(".gen", W_OK | X_OK);
+ if (ret == -1)
+ {
+ perror("access()");
+ return false;
+ }
+
+ }
+ else
+ {
+ ret = mkdir(".gen", 0777);
+ if (ret != 0)
+ {
+ perror("mkdir()");
+ return false;
+ }
+
+ }
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* fd = descripteur de flux ouvert en écriture. *
* prefix = type d'encodage à répercuter sur le nom de fichier. *
* name = nom brut du fichier à ouvrir. *
* ext = extension à donner au fichier à ouvrir. *
-* exist = indique si le fichier était présent avant. [OUT] *
* *
-* Description : Ouvre un fichier en écriture pour y placer du code. *
+* Description : Imprime dans un flux donné un commentaire de propriété. *
* *
-* Retour : Descripteur du fichier ouvert ou -1 en cas d'échec. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static int create_code_file(const rented_coder *coder, const char *dir, const char *prefix, const char *name, char ext, bool *exist)
+static void write_owner_comments(const rented_coder *coder, int fd, const char *prefix, const char *name, char ext)
{
- int result; /* Descripteur à retourner */
- size_t length; /* Taille du nom de fichier */
- char *pathname; /* Chemin d'accès à constituer */
+ dprintf(fd, "\n");
+
+ dprintf(fd, "/* Chrysalide - Outil d'analyse de fichiers binaires\n");
+ dprintf(fd, " * %s%s.%c - traduction d'instructions ARMv7\n", prefix, name, ext);
+ dprintf(fd, " *\n");
+ dprintf(fd, " * %s\n", coder->copyright);
+ dprintf(fd, " *\n");
+ dprintf(fd, " * This file is part of Chrysalide.\n");
+ dprintf(fd, " *\n");
+ dprintf(fd, " * Chrysalide is free software; you can redistribute it and/or modify\n");
+ dprintf(fd, " * it under the terms of the GNU General Public License as published by\n");
+ dprintf(fd, " * the Free Software Foundation; either version 3 of the License, or\n");
+ dprintf(fd, " * (at your option) any later version.\n");
+ dprintf(fd, " *\n");
+ dprintf(fd, " * Chrysalide is distributed in the hope that it will be useful,\n");
+ dprintf(fd, " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
+ dprintf(fd, " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
+ dprintf(fd, " * GNU General Public License for more details.\n");
+ dprintf(fd, " *\n");
+ dprintf(fd, " * You should have received a copy of the GNU General Public License\n");
+ dprintf(fd, " * along with Foobar. If not, see <http://www.gnu.org/licenses/>.\n");
+ dprintf(fd, " */\n");
+
+ dprintf(fd, "\n");
+ dprintf(fd, "\n");
- length = strlen(coder->outdir) + 1 + strlen(dir) + 1 + strlen(prefix) + strlen(name) + 3;
- pathname = (char *)calloc(length, sizeof(char));
- snprintf(pathname, length, "%s/%s/%s%s.%c", coder->outdir, dir, prefix, name, ext);
+}
- *exist = (access(pathname, W_OK) == 0);
- result = open(pathname, O_WRONLY | O_CREAT | O_APPEND, 0644);
- if (result == -1) perror("open()");
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* prefix = type d'encodage à répercuter sur le nom de fichier. *
+* name = nom brut du fichier à ouvrir. *
+* ext = extension à donner au fichier à ouvrir. *
+* *
+* Description : Construit un chemin d'accès à un modèle de fichier de code. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *build_template_filename(const rented_coder *coder, const char *prefix, const char *name, char ext)
+{
+ 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);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* prefix = type d'encodage à répercuter sur le nom de fichier. *
+* name = nom brut du fichier à ouvrir. *
+* ext = extension à donner au fichier à ouvrir. *
+* *
+* Description : Définit un modèle d'en-tête de définitions. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool create_template_file(const rented_coder *coder, const char *prefix, const char *name, char ext)
+{
+ char *pathname; /* Chemin d'accès à constituer */
+ bool exist; /* Note une présence établie */
+ int fd; /* Flux ouvert pour création */
+ char *uprefix; /* Préfixe en majuscule */
+ char *uname; /* Nom en majuscule */
+
+ if (!check_gen_dir(coder))
+ return false;
+
+ pathname = build_template_filename(coder, prefix, name, ext);
+
+ exist = (access(pathname, W_OK) == 0);
+ if (exist)
+ {
+ free(pathname);
+ return true;
+ }
+
+ fd = open(pathname, O_WRONLY | O_CREAT/* | O_TRUNC*/, 0644);
+ if (fd == -1) perror("open()");
free(pathname);
- if (!*exist && result != -1)
+ if (fd != -1)
{
- dprintf(result, "\n");
-
- dprintf(result, "/* Chrysalide - Outil d'analyse de fichiers binaires\n");
- dprintf(result, " * %s%s.%c - traduction d'instructions ARMv7\n", prefix, name, ext);
- dprintf(result, " *\n");
- dprintf(result, " * %s\n", coder->copyright);
- dprintf(result, " *\n");
- dprintf(result, " * This file is part of Chrysalide.\n");
- dprintf(result, " *\n");
- dprintf(result, " * Chrysalide is free software; you can redistribute it and/or modify\n");
- dprintf(result, " * it under the terms of the GNU General Public License as published by\n");
- dprintf(result, " * the Free Software Foundation; either version 3 of the License, or\n");
- dprintf(result, " * (at your option) any later version.\n");
- dprintf(result, " *\n");
- dprintf(result, " * Chrysalide is distributed in the hope that it will be useful,\n");
- dprintf(result, " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
- dprintf(result, " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
- dprintf(result, " * GNU General Public License for more details.\n");
- dprintf(result, " *\n");
- dprintf(result, " * You should have received a copy of the GNU General Public License\n");
- dprintf(result, " * along with Foobar. If not, see <http://www.gnu.org/licenses/>.\n");
- dprintf(result, " */\n");
-
- dprintf(result, "\n");
- dprintf(result, "\n");
+ write_owner_comments(coder, fd, prefix, name, ext);
+
+ if (ext == 'h')
+ {
+ uprefix = make_string_upper(strdup(prefix));
+ uname = make_string_upper(strdup(name));
+
+ dprintf(fd, "#ifndef %s_%s%s_H\n", coder->header, uprefix, uname);
+ dprintf(fd, "#define %s_%s%s_H\n", coder->header, uprefix, uname);
+
+ free(uprefix);
+ free(uname);
+
+ dprintf(fd, "\n");
+ dprintf(fd, "\n");
+ dprintf(fd, "##INCLUDES##\n");
+ dprintf(fd, "\n");
+ dprintf(fd, "\n");
+ dprintf(fd, "\n");
+
+ }
+ else
+ {
+ dprintf(fd, "#include \"%sopcodes.h\"\n", prefix);
+ dprintf(fd, "\n");
+ dprintf(fd, "##INCLUDES##\n");
+
+ }
+
+ close(fd);
}
+ return (fd != -1);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* intput = fichier d'entrée initial à référencer. *
+* prefix = type d'encodage à répercuter sur le nom de fichier. *
+* name = nom brut du fichier à ouvrir. *
+* ext = extension à donner au fichier à ouvrir. *
+* *
+* Description : Construit un chemin d'accès à un fichier de code source. *
+* *
+* Retour : Chaîne de caractères à libérer de la mémoire après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *build_code_filename(const rented_coder *coder, const char *input, const char *prefix, const char *name, char ext)
+{
+ char *result; /* Chaîne construite à renvoyer*/
+ char *orig; /* Fichier d'origine tronqué */
+ char *point; /* Position d'un point */
+ size_t length; /* Taille du nom de fichier */
+
+ orig = strdup(input);
+
+ 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);
+
+ free(orig);
+
+ return result;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* intput = fichier d'entrée initial à référencer. *
+* prefix = type d'encodage à répercuter sur le nom de fichier. *
+* name = nom brut du fichier à ouvrir. *
+* ext = extension à donner au fichier à ouvrir. *
+* *
+* Description : Ouvre un fichier en écriture pour y placer du code. *
+* *
+* Retour : Descripteur du fichier ouvert ou -1 en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int create_code_file(const rented_coder *coder, const char *input, const char *prefix, const char *name, char ext)
+{
+ int result; /* Descripteur à retourner */
+ char *pathname; /* Chemin d'accès à constituer */
+
+ if (!check_gen_dir(coder))
+ return -1;
+
+ pathname = build_code_filename(coder, input, prefix, name, ext);
+
+ result = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (result == -1) perror("open()");
+
+ free(pathname);
+
return result;
}
@@ -451,11 +653,11 @@ static int create_code_file(const rented_coder *coder, const char *dir, const ch
bool dump_all_routines_using_coder(const rented_coder *coder)
{
bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
+ size_t i; /* Boucle de parcours #1 */
const string_exch *encoding; /* Type d'encodage visé */
- bool exist; /* Présence du fichier visé ? */
+ size_t j; /* Boucle de parcours #2 */
+ char *remove; /* Chemin de suppression */
int header_fd; /* Fichier de déclarations */
- char *uname; /* Nom en majuscule */
char *dash; /* Présence d'un tiret ? */
char *filename; /* Nom de fichier commun */
int code_fd; /* Fichier de définitions */
@@ -466,69 +668,132 @@ bool dump_all_routines_using_coder(const rented_coder *coder)
{
encoding = find_encoding(coder->pp, i);
- /* Fichier de déclarations */
+ /* On s'assure qu'il existe bien une version pour l'encodage visé... */
- header_fd = create_code_file(coder, "opcodes", encoding->dest, "opcodes", 'h', &exist);
- if (header_fd == -1) return false;
+ for (j = 0; j < coder->specs_count; j++)
+ if (has_encoding_spec_prefix(coder->specs[j], encoding->src))
+ break;
- if (!exist)
+ /* Suppressions ? */
+ if (j == coder->specs_count)
{
- uname = make_string_upper(strdup(encoding->dest));
+ /* Fichier de déclarations */
- dprintf(header_fd, "#ifndef %s_%sOPCODES_OPCODES_H\n", coder->header, uname);
- dprintf(header_fd, "#define %s_%sOPCODES_OPCODES_H\n", coder->header, uname);
+ /*
+ remove = build_template_filename(coder, encoding->dest, "opcodes", 'h');
+ unlink(remove);
+ free(remove);
+ */
- free(uname);
+ remove = build_code_filename(coder, coder->input, encoding->dest, "opcodes", 'h');
+ unlink(remove);
+ free(remove);
- dprintf(header_fd, "\n");
- dprintf(header_fd, "\n");
- dprintf(header_fd, "##INCLUDES##\n");
- dprintf(header_fd, "\n");
- dprintf(header_fd, "\n");
- dprintf(header_fd, "\n");
+ /* Fichier de définitions */
- }
+ dash = strchr(coder->ins, '-');
- /* Fichier de définitions */
+ if (dash == NULL)
+ {
+ /*
+ remove = build_template_filename(coder, encoding->dest, coder->ins, 'c');
+ unlink(remove);
+ free(remove);
+ */
- dash = strchr(coder->ins, '-');
+ remove = build_code_filename(coder, coder->input, encoding->dest, coder->ins, 'c');
+ unlink(remove);
+ free(remove);
- if (dash == NULL)
- code_fd = create_code_file(coder, "opcodes", encoding->dest, coder->ins, 'c', &exist);
+ }
- else
- {
- filename = strdup(coder->ins);
+ else
+ {
+ filename = strdup(coder->ins);
- dash = strchr(filename, '-');
- *dash = '\0';
+ dash = strchr(filename, '-');
+ *dash = '\0';
- code_fd = create_code_file(coder, "opcodes", encoding->dest, filename, 'c', &exist);
+ /*
+ remove = build_template_filename(coder, encoding->dest, filename, 'c');
+ unlink(remove);
+ free(remove);
+ */
- free(filename);
+ remove = build_code_filename(coder, coder->input, encoding->dest, filename, 'c');
+ unlink(remove);
+ free(remove);
+
+ }
}
- if (!exist)
+ /* Créations ? */
+ else
{
- dprintf(code_fd, "#include \"%sopcodes.h\"\n", encoding->dest);
- dprintf(code_fd, "\n");
- dprintf(code_fd, "##INCLUDES##\n");
+ /* Fichier de déclarations */
- }
+ if (!create_template_file(coder, encoding->dest, "opcodes", 'h'))
+ return false;
- if (code_fd == -1)
- {
- close(header_fd);
- return false;
- }
+ header_fd = create_code_file(coder, coder->input, encoding->dest, "opcodes", 'h');
+ if (header_fd == -1) return false;
+
+ /* Fichier de définitions */
+
+ dash = strchr(coder->ins, '-');
+
+ if (dash == NULL)
+ {
+ if (!create_template_file(coder, encoding->dest, coder->ins, 'c'))
+ return false;
+
+ code_fd = create_code_file(coder, coder->input, encoding->dest, coder->ins, 'c');
+
+ }
+
+ else
+ {
+ filename = strdup(coder->ins);
+
+ dash = strchr(filename, '-');
+ *dash = '\0';
- /* Production de code... */
+ if (!create_template_file(coder, encoding->dest, filename, 'c'))
+ return false;
- result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd);
+ code_fd = create_code_file(coder, coder->input, encoding->dest, filename, 'c');
- close(header_fd);
- close(code_fd);
+ free(filename);
+
+ }
+
+ if (code_fd == -1)
+ {
+ close(header_fd);
+
+ /*
+ remove = build_template_filename(coder, encoding->dest, "opcodes", 'h');
+ unlink(remove);
+ free(remove);
+ */
+
+ remove = build_code_filename(coder, coder->input, encoding->dest, "opcodes", 'h');
+ unlink(remove);
+ free(remove);
+
+ return false;
+
+ }
+
+ /* Production de code... */
+
+ result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd);
+
+ close(header_fd);
+ close(code_fd);
+
+ }
}
@@ -583,8 +848,12 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
}
- /* Rien n'a été trouvé à faire... */
- if (wide == -1) goto damsic_exit;
+ /**
+ * Rien n'a été trouvé à faire...
+ * Cette situation doit normalement être écartée par l'appelant,
+ * afin d'éviter de constituer des fichiers vides.
+ */
+ assert(wide != -1);
/* Désassemblage : déclaration */
@@ -649,8 +918,6 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st
dprintf(cfd, "}\n");
dprintf(cfd, "\n");
- damsic_exit:
-
free(keyword);
return result;
diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h
index e72764c..aadb2d4 100644
--- a/tools/d2c/coder.h
+++ b/tools/d2c/coder.h
@@ -50,6 +50,9 @@ void delete_coder(rented_coder *);
/* Détermine si les propriétés de base d'un codeur sont là. */
bool do_basic_checks_with_coder(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 répertoire de base pour les sorties de code. */
void set_coder_output_directory(rented_coder *, const char *);
diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk
index 25596cf..36bb38e 100644
--- a/tools/d2c/d2c.mk
+++ b/tools/d2c/d2c.mk
@@ -9,10 +9,6 @@ fix_verbose = $(fix_verbose_@AM_V@)
fix_verbose_ = $(fix_verbose_@AM_DEFAULT_V@)
fix_verbose_0 = echo " FIX " `basename $$f`;
-fix2_verbose = $(fix2_verbose_@AM_V@)
-fix2_verbose_ = $(fix2_verbose_@AM_DEFAULT_V@)
-fix2_verbose_0 = echo " FIX " `basename $<`;
-
# D2C_BIN =
# D2C_OUTDIR =
# D2C_ARCH =
@@ -23,9 +19,9 @@ fix2_verbose_0 = echo " FIX " `basename $<`;
SUFFIXES = .g
.d.g:
- $(d2c_verbose)$(D2C_BIN) -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) < $<
+ $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) < $<
@touch $@
# Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t
untabify_disass:
- find $(D2C_OUTDIR)/opcodes -name '*c' -exec grep -q $$'\t' {} \; -exec sed -i 's/\t/ /g' {} \;
+ @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
new file mode 100644
index 0000000..bd5c379
--- /dev/null
+++ b/tools/d2c/d2c_genmakefile.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+
+if [ $# -lt 4 ]; then
+
+ echo "Usage: $0 <working dir> <input dir> <global mk> <arch [arch [arch ...]]"
+ exit 1
+
+fi
+
+workingdir=$1
+input=$2
+globalmk=$3
+
+shift 3
+
+OLDPWD=$PWD
+
+MAKEFILE_TMP=gencode.mk.tmp
+MAKEFILE_EXT=gencode.mk
+
+cd ${workingdir}
+
+echo=`which echo`
+
+rm -f ${MAKEFILE_TMP}
+$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`
+
+# 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}
+
+ has_header=""
+
+ for op in $OPCODES;
+ do
+ template="${input}/*${arch}_.${op}.c"
+
+ sources=`ls $template 2> /dev/null`
+
+ if [ -z "${sources}" ]; then
+ continue
+ fi
+
+ for src in ${sources};
+ do
+ has_header="yes"
+ $echo -ne " \\" >> ${MAKEFILE_TMP}
+ $echo -ne "\n\t" >> ${MAKEFILE_TMP}
+ $echo -n ${src} | sed "s/${op}.c$/opcodes.h/" >> ${MAKEFILE_TMP}
+ done
+
+ done
+
+ $echo >> ${MAKEFILE_TMP}
+ $echo >> ${MAKEFILE_TMP}
+
+ $echo -n "${arch}_opcodes.h: " >> ${MAKEFILE_TMP}
+ $echo "\$(${arch}_HEADER_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+
+ if [ -z "${has_header}" ]; then
+
+ $echo -e "\techo > \$@" >> ${MAKEFILE_TMP}
+
+ else
+
+ $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.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}
+ $echo -en '`cat \$@ | grep "#define" | cut -d " " -f 2`' >> ${MAKEFILE_TMP}
+ $echo -e " */\" >> \$@" >> ${MAKEFILE_TMP}
+
+ fi
+
+ $echo >> ${MAKEFILE_TMP}
+
+done
+
+$echo >> ${MAKEFILE_TMP}
+
+
+# Génération des codes d'instructions
+
+for op in $OPCODES;
+do
+ for arch in $*;
+ do
+ template="${input}/*${arch}_.${op}.c"
+
+ sources=`ls $template 2> /dev/null`
+
+ if [ -z "${sources}" ]; then
+ continue
+ fi
+
+ $echo -n "${op}_${arch}_FILES =" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+
+ for src in ${sources};
+ do
+ $echo -ne " \\" >> ${MAKEFILE_TMP}
+ $echo -ne "\n\t${src}" >> ${MAKEFILE_TMP}
+ done
+
+ $echo >> ${MAKEFILE_TMP}
+ $echo >> ${MAKEFILE_TMP}
+
+ $echo -n "${arch}_${op}.c: " >> ${MAKEFILE_TMP}
+ $echo "\$(${op}_${arch}_FILES)" | tr [a-z] [A-Z] >> ${MAKEFILE_TMP}
+
+ $echo -e "\t\$(cini_verbose)cat ${input}/${arch}_.${op}.tmpl.c > \$@" >> ${MAKEFILE_TMP}
+ $echo -e "\t\$(cgen_verbose)cat \$^ >> \$@" >> ${MAKEFILE_TMP}
+
+ $echo >> ${MAKEFILE_TMP}
+
+ done
+
+done
+
+$echo >> ${MAKEFILE_TMP}
+
+# Génération de la liste des sources
+
+$echo -n "GENERATED_FILES =" >> ${MAKEFILE_TMP}
+
+for arch in $*;
+do
+ $echo -ne " \\" >> ${MAKEFILE_TMP}
+ $echo -ne "\n\t${arch}_opcodes.h" >> ${MAKEFILE_TMP}
+
+ for op in $OPCODES;
+ do
+ template="${input}/*${arch}_.${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}
+ continue
+ fi
+
+ done
+
+done
+
+$echo >> ${MAKEFILE_TMP}
+
+$echo >> ${MAKEFILE_TMP}
+
+# Validation finale
+
+if [ ! -f ]; then
+
+ rm -rf ${MAKEFILE_EXT}
+ mv ${MAKEFILE_TMP} ${MAKEFILE_EXT}
+
+else
+
+ hash_tmp=`md5sum ${MAKEFILE_TMP} | cut -d ' ' -f 1`
+ hash_ext=`md5sum ${MAKEFILE_EXT} | cut -d ' ' -f 1`
+
+ if [ "${hash_tmp}" = "${hash_ext}" ]; then
+
+ rm -f ${MAKEFILE_TMP}
+
+ echo "${MAKEFILE_EXT} is up to date."
+
+ else
+
+ rm -f ${MAKEFILE_EXT}
+ mv ${MAKEFILE_TMP} ${MAKEFILE_EXT}
+
+ echo "${MAKEFILE_EXT} is updated."
+
+ fi
+
+fi
+
+cd ${OLDPWD}
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y
index 5ae93c8..b1519a1 100644
--- a/tools/d2c/d2c_gram.y
+++ b/tools/d2c/d2c_gram.y
@@ -354,6 +354,7 @@ int main(int argc, char **argv)
static struct option long_options[] = {
{ "help", no_argument, NULL, 'h' },
+ { "input", required_argument, NULL, 'i' },
{ "dir", required_argument, NULL, 'd' },
{ "arch", required_argument, NULL, 'a' },
{ "header", required_argument, NULL, 'H' },
@@ -374,7 +375,7 @@ int main(int argc, char **argv)
while (!has_error)
{
- ret = getopt_long(argc, argv, "hd:a:H:e:M:", long_options, &index);
+ ret = getopt_long(argc, argv, "hi:d:a:H:e:M:", long_options, &index);
if (ret == -1) break;
switch (ret)
@@ -383,6 +384,10 @@ int main(int argc, char **argv)
need_help = true;
break;
+ case 'i':
+ set_coder_input_file(coder, optarg);
+ break;
+
case 'd':
set_coder_output_directory(coder, optarg);
break;
diff --git a/tools/d2c/globalgen.mk b/tools/d2c/globalgen.mk
new file mode 100644
index 0000000..ede457a
--- /dev/null
+++ b/tools/d2c/globalgen.mk
@@ -0,0 +1,12 @@
+
+cini_verbose = $(cini_verbose_@AM_V@)
+cini_verbose_ = $(cini_verbose_@AM_DEFAULT_V@)
+cini_verbose_0 = @echo " INIT " `basename $@`;
+
+cgen_verbose = $(cgen_verbose_@AM_V@)
+cgen_verbose_ = $(cgen_verbose_@AM_DEFAULT_V@)
+cgen_verbose_0 = @echo " GEN " `basename $@`;
+
+cfini_verbose = $(cfini_verbose_@AM_V@)
+cfini_verbose_ = $(cfini_verbose_@AM_DEFAULT_V@)
+cfini_verbose_0 = @echo " FINI " `basename $@`;