summaryrefslogtreecommitdiff
path: root/tools/d2c/coder.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-01-30 17:23:16 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-01-30 17:23:16 (GMT)
commit792b330c1bbe573a591687d25e14d4cd1eccd3c6 (patch)
tree9a3e0955205c0221ea5db03b1f3a4d56846efed2 /tools/d2c/coder.c
parentc922b6b9c841a97dd948755658cff07b2c6762ff (diff)
Introduced a format switch to distinguish different kinds of definitions.
Diffstat (limited to 'tools/d2c/coder.c')
-rw-r--r--tools/d2c/coder.c248
1 files changed, 232 insertions, 16 deletions
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;
+
+}