diff options
Diffstat (limited to 'tools/d2c/coder.c')
-rw-r--r-- | tools/d2c/coder.c | 1656 |
1 files changed, 1238 insertions, 418 deletions
diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c index 65e9605..e286a1d 100644 --- a/tools/d2c/coder.c +++ b/tools/d2c/coder.c @@ -27,13 +27,10 @@ #include <assert.h> #include <fcntl.h> #include <malloc.h> -#include <regex.h> -#include <stdint.h> #include <stdio.h> #include <string.h> +#include <time.h> #include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> #include "helpers.h" @@ -47,8 +44,6 @@ 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 */ @@ -61,6 +56,11 @@ struct _rented_coder char *raw_details; /* Eventuels compléments bruts */ char *details; /* Eventuels compléments */ + instr_id *id; /* Gestionnaire d'identifiant */ + instr_desc *desc; /* Gestionnaire de description */ + + bool useless; /* Instruction non utilisée */ + encoding_spec **specs; /* Définitions déjà en place */ size_t specs_count; /* Nombre de ces définitions */ encoding_spec *cur_spec; /* Définition courante */ @@ -69,32 +69,58 @@ struct _rented_coder +/* --------------------------- REPRESENTATION D'ENCODAGES --------------------------- */ + + +/* Détermine le nombre de bits analysés lors d'un désassemblage. */ +static unsigned int get_bit_width_for_encoding_spec(const rented_coder *, const string_exch *); + + + /* --------------------------- GENERATIONS DE CODE SOURCE --------------------------- */ -/* S'assure de la présence du répertoire de sortie du code. */ -static bool check_gen_dir(const rented_coder *); +/* Ouvre un fichier principal en écriture pour y placer du code. */ +static int open_instr_header_file(const rented_coder *, const output_info *, const char *, bool *); + +/* Ouvre un fichier principal en écriture pour y placer du code. */ +static int open_instr_code_file(const rented_coder *, const output_info *, const char *, bool *); + +/* Ouvre un fichier global en écriture pour y placer du code. */ +static int open_global_header_file(const rented_coder *, const output_info *, const char *, bool *); + +/* Imprime dans un flux donné un commentaire de propriété. */ +static void write_header_file_license(int, const output_info *, const char *, const char *); /* Imprime dans un flux donné un commentaire de propriété. */ -static void write_owner_comments(const rented_coder *, int, const char *, const char *, char); +static void write_code_file_license(int, const output_info *, const char *, const char *); + +/* Initialise le contenu utile du fichier des instructions. */ +static void init_coder_opcodes_file(int, const output_info *, const char *); + +/* Initialise le contenu utile d'un fichier d'instructions. */ +static void init_coder_code_file(int, const char *); + +/* Centralise l'impression du nom de fonction de désassemblage. */ +static void write_read_function_name(int fd, const char *, const string_exch *, const 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); +/* Génère ou complète un fichier contenant le code C principal. */ +static bool output_coder_raw(const rented_coder *, const output_info *, const string_exch *, const encoding_spec *, int, int); -/* 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); +/* Génère ou complète un fichier contenant le code C principal. */ +static bool output_coder_main_raw(const rented_coder *, const output_info *, const string_exch *, int, int); -/* 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); +/* Génère ou complète un fichier contenant le code C principal. */ +static bool output_coder_format(const rented_coder *, const output_info *, const string_exch *, const encoding_spec *, int, int); -/* 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); +/* Initialise le contenu utile du fichier des identifiants. */ +static void init_coder_identifiers_file(int, const output_info *); -/* 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); +/* Initialise le contenu utile du fichier des mots clefs. */ +static void init_coder_keywords_file(int, const output_info *); -/* 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); +/* Initialise le contenu utile du fichier des descriptions. */ +static void init_coder_descriptions_file(int, const output_info *); @@ -105,7 +131,7 @@ static bool dump_all_matching_specs_from_format(const rented_coder *, const stri /****************************************************************************** * * -* Paramètres : - * +* Paramètres : pp = préprocesseur déjà chargé à intégrer. * * * * Description : Débute la définition d'une fonction de désassemblage. * * * @@ -115,16 +141,21 @@ static bool dump_all_matching_specs_from_format(const rented_coder *, const stri * * ******************************************************************************/ -rented_coder *create_coder(void) +rented_coder *create_coder(pre_processor *pp) { rented_coder *result; /* Structure à renvoyer */ result = (rented_coder *)calloc(1, sizeof(rented_coder)); - result->pp = create_pre_processor(); + result->pp = pp; + + result->id = create_instruction_id(); + result->desc = create_instruction_description(); result->cur_spec = create_encoding_spec(); + result->useless = false; + return result; } @@ -157,6 +188,9 @@ void delete_coder(rented_coder *coder) free(coder->details); } + delete_instruction_id(coder->id); + delete_instruction_description(coder->desc); + for (i = 0; i < coder->specs_count; i++) delete_encoding_spec(coder->specs[i]); @@ -184,15 +218,14 @@ void delete_coder(rented_coder *coder) bool do_basic_checks_with_coder(const rented_coder *coder) { - 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; + */ + return false; } @@ -248,32 +281,13 @@ void set_coder_input_file(rented_coder *coder, const char *input) * 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. * -* * -* Description : Spécifie le répertoire de base pour les sorties de code. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void set_coder_output_directory(rented_coder *coder, const char *outdir) -{ - coder->outdir = outdir; - -} +*/ /****************************************************************************** @@ -336,23 +350,10 @@ void set_coder_const_prefix(rented_coder *coder, const char *prefix) } -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* * -* Description : Fournit le pré-processeur du compilateur. * -* * -* Retour : Pré-processeur à manipuler. * -* * -* Remarques : - * -* * -******************************************************************************/ - -pre_processor *get_coder_pre_proc(const rented_coder *coder) -{ - return coder->pp; -} +/* ---------------------------------------------------------------------------------- */ +/* INFORMATIONS GENERALES */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** @@ -392,6 +393,110 @@ void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, char sep, } +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* * +* Description : Fournit la désignation nominale d'une instruction. * +* * +* Retour : Désignation nominale à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *get_coder_nominal_name(const rented_coder *coder) +{ + char *result; /* Désignation à retourner */ + + if (coder->separator == '\0') + result = strdup(coder->ins); + + else + asprintf(&result, "%s%c%s", coder->ins, coder->separator, coder->raw_details); + + return result; + +} + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* * +* Description : Fournit la désignation complète d'une instruction. * +* * +* Retour : Désignation complète à libérer de la mémoire. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *get_coder_code_name(const rented_coder *coder) +{ + char *result; /* Désignation à retourner */ + char *keyword; /* Mot clef appelable en code */ + char *details; /* Compléments de distinction */ + + keyword = make_callable(coder->ins, false); + + if (coder->separator == '\0') + result = keyword; + + else + { + details = make_callable(coder->raw_details, true); + + asprintf(&result, "%s%s", keyword, details); + + free(keyword); + + free(details); + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* * +* Description : Fournit le gestionnaire des définitions d'identifiant. * +* * +* Retour : Structure assurant la définition d'identifiant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +instr_id *get_coder_instruction_id(const rented_coder *coder) +{ + return coder->id; + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* * +* Description : Fournit le gestionnaire de description d'identifiant. * +* * +* Retour : Structure assurant la description d'identifiant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +instr_desc *get_coder_instruction_desc(const rented_coder *coder) +{ + return coder->desc; + +} + + /* ---------------------------------------------------------------------------------- */ /* REPRESENTATION D'ENCODAGES */ @@ -400,7 +505,7 @@ void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, char sep, /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * * * * Description : Fournit un lien vers les spécifications courantes. * * * @@ -448,66 +553,58 @@ void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index) } - -/* ---------------------------------------------------------------------------------- */ -/* GENERATIONS DE CODE SOURCE */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* Paramètres : coder = gestion automatique de l'écriture de code. * +* enc_name = désignation du type d'encodage visé. * * * -* Description : S'assure de la présence du répertoire de sortie du code. * +* Description : Détermine le nombre de bits analysés lors d'un désassemblage.* * * -* Retour : Bilan de l'opération. * +* Retour : Nombre de bits interprété. * * * * Remarques : - * * * ******************************************************************************/ -static bool check_gen_dir(const rented_coder *coder) +static unsigned int get_bit_width_for_encoding_spec(const rented_coder *coder, const string_exch *enc_name) { - bool has_gen; /* Répertoire de sortie présent*/ - int ret; /* Bilan d'un appel externe */ + unsigned int result; /* Taille à retourner */ + size_t i; /* Boucle de parcours */ + encoding_spec *spec; /* Définition à traiter */ + coding_bits *bits; /* Gestionnaire de bits */ - has_gen = (access(".gen", F_OK) == 0); + result = -1; - if (has_gen) + for (i = 0; i < coder->specs_count; i++) { - ret = access(".gen", W_OK | X_OK); - if (ret == -1) - { - perror("access()"); - return false; - } + spec = coder->specs[i]; - } - else - { - ret = mkdir(".gen", 0777); - if (ret != 0) - { - perror("mkdir()"); - return false; - } + if (!has_encoding_spec_prefix(spec, enc_name->src)) + continue; + + bits = get_bits_in_encoding_spec(spec); + result = count_coded_bits(bits); + break; } - return true; + /** + * 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(result != -1); + + return result; } /****************************************************************************** * * -* 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. * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * * * -* Description : Imprime dans un flux donné un commentaire de propriété. * +* Description : Marque une instruction comme non utilisée. * * * * Retour : - * * * @@ -515,69 +612,59 @@ static bool check_gen_dir(const rented_coder *coder) * * ******************************************************************************/ -static void write_owner_comments(const rented_coder *coder, int fd, const char *prefix, const char *name, char ext) +void mark_coder_as_useless(rented_coder *coder) { - dprintf(fd, "\n"); + coder->useless = true; - 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"); -} + +/* ---------------------------------------------------------------------------------- */ +/* GENERATIONS DE CODE SOURCE */ +/* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * * prefix = type d'encodage à répercuter sur le nom de fichier. * -* name = nom brut du fichier à ouvrir. * -* ext = extension à donner au fichier à ouvrir. * +* new = dit si l'opération a abouti à une création. [OUT] * * * -* Description : Construit un chemin d'accès à un modèle de fichier de code. * +* Description : Ouvre un fichier principal en écriture pour y placer du code.* * * -* Retour : Chaîne de caractères à libérer de la mémoire après usage. * +* Retour : Descripteur du fichier ouvert ou -1 en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static char *build_template_filename(const rented_coder *coder, const char *prefix, const char *name, char ext) +static int open_instr_header_file(const rented_coder *coder, const output_info *info, const char *prefix, bool *new) { - char *result; /* Chaîne construite à renvoyer*/ - size_t length; /* Taille du nom de fichier */ + int result; /* Descripteur à retourner */ + char *pathname; /* Chemin d'accès à constituer */ + int ret; /* Test d'existence du fichier */ + int flags; /* Mode d'accès au fichier */ - 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); - } + if (prefix != NULL) + asprintf(&pathname, "%s%s_opcodes.h", info->directory, prefix); 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); - } + asprintf(&pathname, "%sopcodes.h", info->directory); + + ret = access(pathname, F_OK); + + *new = (ret != 0); + + if (*new) + flags = O_WRONLY | O_CREAT; + else + flags = O_WRONLY | O_APPEND; + + result = open(pathname, flags, 0644); + if (result == -1) perror("open()"); + + free(pathname); return result; @@ -587,320 +674,365 @@ static char *build_template_filename(const rented_coder *coder, const char *pref /****************************************************************************** * * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * * prefix = type d'encodage à répercuter sur le nom de fichier. * -* name = nom brut du fichier à ouvrir. * -* ext = extension à donner au fichier à ouvrir. * +* new = dit si l'opération a abouti à une création. [OUT] * * * -* Description : Définit un modèle d'en-tête de définitions. * +* Description : Ouvre un fichier principal en écriture pour y placer du code.* * * -* Retour : Bilan de l'opération. * +* Retour : Descripteur du fichier ouvert ou -1 en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static bool create_template_file(const rented_coder *coder, const char *prefix, const char *name, char ext) +static int open_instr_code_file(const rented_coder *coder, const output_info *info, const char *prefix, bool *new) { + int result; /* Descripteur à retourner */ + char *group; /* Regroupement des similarités*/ + char *sep; /* Eventuelle séparation */ 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 */ - - if (!check_gen_dir(coder)) - return false; + int ret; /* Test d'existence du fichier */ + int flags; /* Mode d'accès au fichier */ - pathname = build_template_filename(coder, prefix, name, ext); - - exist = (access(pathname, W_OK) == 0); - if (exist) - { - free(pathname); - return true; - } + group = strdup(coder->ins); - fd = open(pathname, O_WRONLY | O_CREAT/* | O_TRUNC*/, 0644); - if (fd == -1) perror("open()"); + sep = index(group, '-'); - free(pathname); - - if (fd != -1) - { - valid_prefix = prefix != NULL ? prefix : ""; - - write_owner_comments(coder, fd, valid_prefix, name, ext); - - if (ext == 'h') - { - uprefix = make_string_upper(strdup(valid_prefix)); - uname = make_string_upper(strdup(name)); + if (sep != NULL) + *sep = '\0'; - dprintf(fd, "#ifndef %s_%s%s_H\n", coder->header, uprefix, uname); - dprintf(fd, "#define %s_%s%s_H\n", coder->header, uprefix, uname); + if (prefix != NULL) + asprintf(&pathname, "%s%s_%s.c", info->directory, prefix, group); + else + asprintf(&pathname, "%s%s.c", info->directory, group); - free(uprefix); - free(uname); + free(group); - dprintf(fd, "\n"); - dprintf(fd, "\n"); - dprintf(fd, "##INCLUDES##\n"); - dprintf(fd, "\n"); - dprintf(fd, "\n"); - dprintf(fd, "\n"); + ret = access(pathname, F_OK); - } - else - { - dprintf(fd, "#include \"%sopcodes.h\"\n", valid_prefix); - dprintf(fd, "\n"); - dprintf(fd, "##INCLUDES##\n"); + *new = (ret != 0); - } + if (*new) + flags = O_WRONLY | O_CREAT; + else + flags = O_WRONLY | O_APPEND; - close(fd); + result = open(pathname, flags, 0644); + if (result == -1) perror("open()"); - } + free(pathname); - return (fd != -1); + 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. * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * +* name = nom du fichier ciblé par l'opération. * +* new = indique si l'opération a créé le fichier ciblé. [OUT]* * * -* Description : Construit un chemin d'accès à un fichier de code source. * +* Description : Ouvre un fichier global en écriture pour y placer du code. * * * -* Retour : Chaîne de caractères à libérer de la mémoire après usage. * +* Retour : Descripteur du fichier ouvert ou -1 en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -static char *build_code_filename(const rented_coder *coder, const char *input, const char *prefix, const char *name, char ext) +static int open_global_header_file(const rented_coder *coder, const output_info *info, const char *name, bool *new) { - 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 */ + int result; /* Descripteur à retourner */ + char *pathname; /* Chemin d'accès à constituer */ + int ret; /* Test d'existence du fichier */ + int flags; /* Mode d'accès au fichier */ - orig = strdup(input); + asprintf(&pathname, "%s%s.h", info->directory, name); - point = strstr(orig, "."); - if (point != NULL) *point = '\0'; + ret = access(pathname, F_OK); - 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); - } + *new = (ret != 0); + + if (*new) + flags = O_WRONLY | O_CREAT; 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); - } + flags = O_WRONLY | O_APPEND; + + result = open(pathname, flags, 0644); + if (result == -1) perror("open()"); - free(orig); + free(pathname); 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. * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* name = nom du fichier ciblé par l'opération. * +* msg = complément d'information à faire paraître. * * * -* 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 *input, const char *prefix, const char *name, char ext) +static void write_header_file_license(int fd, const output_info *info, const char *name, const char *msg) { - int result; /* Descripteur à retourner */ - char *pathname; /* Chemin d'accès à constituer */ - - if (!check_gen_dir(coder)) - return -1; + time_t seconds; /* Temps écoulé depuis T0 */ + struct tm cur_date; /* Informations sur la date */ - pathname = build_code_filename(coder, input, prefix, name, ext); + time(&seconds); + localtime_r(&seconds, &cur_date); - result = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (result == -1) perror("open()"); + dprintf(fd, "\n"); - free(pathname); + dprintf(fd, "/* Chrysalide - Outil d'analyse de fichiers binaires\n"); + dprintf(fd, " * %s.h - %s %s\n", name, msg, info->arch); + dprintf(fd, " *\n"); + dprintf(fd, " * Copyright (C) %d Cyrille Bagard\n", 1900 + cur_date.tm_year); + 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.\n"); + dprintf(fd, " */\n"); - return result; + dprintf(fd, "\n"); + dprintf(fd, "\n"); } /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement de l'humain.* +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* name = nom du fichier ciblé par l'opération. * +* copyright = droits d'auteur à faire valoir. * * * -* Description : Débute la définition des fonctions issues des spécifications.* +* Description : Imprime dans un flux donné un commentaire de propriété. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -bool dump_all_routines_using_coder(const rented_coder *coder) +static void write_code_file_license(int fd, const output_info *info, const char *name, const char *copyright) { - bool result; /* Bilan à retourner */ - size_t i; /* Boucle de parcours #1 */ - const string_exch *encoding; /* Type d'encodage visé */ - size_t j; /* Boucle de parcours #2 */ - char *remove; /* Chemin de suppression */ - int header_fd; /* Fichier de déclarations */ - char *dash; /* Présence d'un tiret ? */ - char *filename; /* Nom de fichier commun */ - int code_fd; /* Fichier de définitions */ + dprintf(fd, "\n"); - result = true; + dprintf(fd, "/* Chrysalide - Outil d'analyse de fichiers binaires\n"); + dprintf(fd, " * %s.c - traduction d'instructions %s\n", name, info->arch); + dprintf(fd, " *\n"); + dprintf(fd, " * %s\n", 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.\n"); + dprintf(fd, " */\n"); - for (i = 0; i < count_encodings(coder->pp) && result; i++) - { - encoding = find_encoding(coder->pp, i); + dprintf(fd, "\n"); + dprintf(fd, "\n"); - /* On s'assure qu'il existe bien une version pour l'encodage visé... */ +} - for (j = 0; j < coder->specs_count; j++) - if (has_encoding_spec_prefix(coder->specs[j], encoding->src)) - break; - /* Suppressions ? */ - if (j == coder->specs_count) - { - /* Fichier de déclarations */ +/****************************************************************************** +* * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* prefix = préfixe lié à une sous-branche de l'architecture. * +* * +* Description : Initialise le contenu utile du fichier des instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - /* - remove = build_template_filename(coder, encoding->dest, "opcodes", 'h'); - unlink(remove); - free(remove); - */ +static void init_coder_opcodes_file(int fd, const output_info *info, const char *prefix) +{ + char *sub; /* Sous-partie à intégrer */ - remove = build_code_filename(coder, coder->input, encoding->dest, "opcodes", 'h'); - unlink(remove); - free(remove); + if (prefix != NULL) + { + sub = strdup(prefix); + make_string_upper(sub); - /* Fichier de définitions */ + dprintf(fd, "#ifndef _%s_%s_OPCODES_H\n", info->guard, sub); + dprintf(fd, "#define _%s_%s_OPCODES_H\n", info->guard, sub); - dash = strchr(coder->ins, '-'); + free(sub); - if (dash == NULL) - { - /* - remove = build_template_filename(coder, encoding->dest, coder->ins, 'c'); - unlink(remove); - free(remove); - */ + } - remove = build_code_filename(coder, coder->input, encoding->dest, coder->ins, 'c'); - unlink(remove); - free(remove); + else + { + dprintf(fd, "#ifndef _%s_OPCODES_H\n", info->guard); + dprintf(fd, "#define _%s_OPCODES_H\n", info->guard); + } - } + dprintf(fd, "\n"); + dprintf(fd, "\n"); - else - { - filename = strdup(coder->ins); + dprintf(fd, "##INCLUDES##\n"); - dash = strchr(filename, '-'); - *dash = '\0'; + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); - /* - remove = build_template_filename(coder, encoding->dest, filename, 'c'); - unlink(remove); - free(remove); - */ +} - remove = build_code_filename(coder, coder->input, encoding->dest, filename, 'c'); - unlink(remove); - free(remove); - } +/****************************************************************************** +* * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* prefix = type d'encodage à répercuter sur un nom de fichier. * +* * +* Description : Initialise le contenu utile d'un fichier d'instructions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ - } +static void init_coder_code_file(int fd, const char *prefix) +{ + if (prefix != NULL) + dprintf(fd, "#include \"%s_opcodes.h\"\n", prefix); + else + dprintf(fd, "#include \"opcodes.h\"\n"); - /* Créations ? */ - else - { - /* Fichier de déclarations */ + dprintf(fd, "\n"); + dprintf(fd, "\n"); - if (!create_template_file(coder, encoding->dest, "opcodes", 'h')) - return false; + dprintf(fd, "##INCLUDES##\n"); - header_fd = create_code_file(coder, coder->input, encoding->dest, "opcodes", 'h'); - if (header_fd == -1) return false; + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); - /* Fichier de définitions */ +} - dash = strchr(coder->ins, '-'); - if (dash == NULL) - { - if (!create_template_file(coder, encoding->dest, coder->ins, 'c')) - return false; +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * +* * +* Description : Génère ou complète un fichier contenant le code C principal. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ - code_fd = create_code_file(coder, coder->input, encoding->dest, coder->ins, 'c'); +bool output_coder_body(const rented_coder *coder, const output_info *info) +{ + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + const string_exch *enc_name; /* Type d'encodage visé */ + size_t j; /* Boucle de parcours #2 */ + int header_fd; /* Fichier de déclarations */ + char *file; /* Nom de fichier final */ + bool header_new; /* Note une création d'entête */ + int code_fd; /* Fichier de définitions */ + bool code_new; /* Note une création de code */ - } + result = true; - else + for (i = 0; i < count_encodings(coder->pp) && result; i++) + { + enc_name = find_encoding(coder->pp, i); + + for (j = 0; j < coder->specs_count; j++) + { + /* On s'assure qu'il existe bien une version pour l'encodage visé... */ + if (!has_encoding_spec_prefix(coder->specs[j], enc_name->src)) + continue; + + header_fd = open_instr_header_file(coder, info, enc_name->dest, &header_new); + if (header_fd == -1) { - filename = strdup(coder->ins); + result = false; + goto ocb_exit; + } - dash = strchr(filename, '-'); - *dash = '\0'; + if (header_new) + { + if (enc_name->dest == NULL) + file = strdup("opcodes"); + else + asprintf(&file, "%s_opcodes", enc_name->dest); - if (!create_template_file(coder, encoding->dest, filename, 'c')) - return false; + write_header_file_license(header_fd, info, file, "prototypes pour la traduction d'instructions"); - code_fd = create_code_file(coder, coder->input, encoding->dest, filename, 'c'); + free(file); - free(filename); + init_coder_opcodes_file(header_fd, info, enc_name->dest); } + code_fd = open_instr_code_file(coder, info, enc_name->dest, &code_new); if (code_fd == -1) { - close(header_fd); + result = false; + goto ocb_exit; + } - /* - remove = build_template_filename(coder, encoding->dest, "opcodes", 'h'); - unlink(remove); - free(remove); - */ + if (code_new) + { + if (enc_name->dest == NULL) + file = strdup(coder->ins); + else + asprintf(&file, "%s_%s", enc_name->dest, coder->ins); - remove = build_code_filename(coder, coder->input, encoding->dest, "opcodes", 'h'); - unlink(remove); - free(remove); + write_code_file_license(code_fd, info, file, coder->copyright); - return false; + free(file); - } + init_coder_code_file(code_fd, enc_name->dest); - /* Production de code... */ + } + else + dprintf(code_fd, "\n"); - switch (coder->type) + switch (info->type) { case IOT_UNDEFINED: assert(false); @@ -908,22 +1040,56 @@ bool dump_all_routines_using_coder(const rented_coder *coder) break; case IOT_RAW: - result = dump_all_matching_specs_in_coder(coder, encoding, header_fd, code_fd); + result = output_coder_raw(coder, info, enc_name, coder->specs[j], header_fd, code_fd); break; case IOT_FORMAT: - result = dump_all_matching_specs_from_format(coder, encoding, header_fd, code_fd); + assert(enc_name->dest == NULL); + result = output_coder_format(coder, info, enc_name, coder->specs[j], header_fd, code_fd); break; } - close(header_fd); - close(code_fd); + } + + /* La suite ne concerne que les formats bruts aboutis... */ + if (!result) break; + if (info->type != IOT_RAW) continue; + + for (j = 0; j < coder->specs_count; j++) + { + /* On s'assure de retrouver une version de l'encodage visé juste avant... */ + if (!has_encoding_spec_prefix(coder->specs[j], enc_name->src)) + continue; + + header_fd = open_instr_header_file(coder, info, enc_name->dest, &header_new); + if (header_fd == -1) + { + result = false; + goto ocb_exit; + } + + assert(!header_new); + + code_fd = open_instr_code_file(coder, info, enc_name->dest, &code_new); + if (code_fd == -1) + { + result = false; + goto ocb_exit; + } + + assert(!code_new); + + result = output_coder_main_raw(coder, info, enc_name, header_fd, code_fd); + + break; } } + ocb_exit: + return result; } @@ -931,12 +1097,39 @@ bool dump_all_routines_using_coder(const rented_coder *coder) /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement d'humain. * +* Paramètres : fd = flux ouvert en écriture. * +* arch = architecture en cours de traitement. * +* sub = encodage choisi comme sous-ensemble d'architecture. * +* name = désignation complète d'une instruction. * +* * +* Description : Centralise l'impression du nom de fonction de désassemblage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void write_read_function_name(int fd, const char *arch, const string_exch *sub, const char *name) +{ + if (sub->dest == NULL) + dprintf(fd, "%s_read_instr_%s", arch, name); + else + dprintf(fd, "%s_read_%s_instr_%s", arch, sub->dest, name); + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion automatique de l'écriture de code. * +* info = précisions quant à la génération. * +* enc_name = désignation du type d'encodage visé. * * 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. * +* Description : Génère ou complète un fichier contenant le code C principal. * * * * Retour : Bilan de l'opération. * * * @@ -944,55 +1137,152 @@ bool dump_all_routines_using_coder(const rented_coder *coder) * * ******************************************************************************/ -static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const string_exch *encoding, int hfd, int cfd) +static bool output_coder_raw(const rented_coder *coder, const output_info *info, const string_exch *enc_name, const encoding_spec *encoding, int hfd, int cfd) { bool result; /* Bilan à retourner */ - char *keyword; /* Mot clef appelable en code */ - unsigned int wide; /* Taille des mots */ - size_t i; /* Boucle de parcours */ - encoding_spec *spec; /* Définition à traiter */ + char *arch; /* Architecture à traiter */ + char *name; /* Désignation à manipuler */ + char *prefix; /* Préfixe employé en suffixe */ coding_bits *bits; /* Gestionnaire de bits */ + unsigned int wide; /* Taille des mots */ size_t maxlen; /* Taille à compléter */ - result = true; + arch = strdup(info->arch_cn); + make_string_lower(arch); - keyword = make_callable(coder->ins, false); + name = get_coder_code_name(coder); - /* Recherche de la taille des mots */ + prefix = build_encoding_spec_prefix(encoding); - wide = -1; + bits = get_bits_in_encoding_spec(encoding); + wide = count_coded_bits(bits); - for (i = 0; i < coder->specs_count; i++) + /* Désassemblage : déclaration */ + + if (0 /* TODO : export seulement */) { - spec = coder->specs[i]; + dprintf(hfd, "/* Décode une forme d'instruction de type '%s'. */\n", coder->ins); - if (!has_encoding_spec_prefix(spec, encoding->src)) - continue; + dprintf(hfd, "GArchInstruction *"); + write_read_function_name(hfd, arch, enc_name, name); + dprintf(hfd, "_%s", prefix); - bits = get_bits_in_encoding_spec(spec); - wide = count_coded_bits(bits); - break; + dprintf(hfd, "("); + dprintf(hfd, "uint%u_t raw", wide); + dprintf(hfd, ");\n"); + + dprintf(hfd, "\n"); } - /** - * 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éfinitions */ + + dprintf(cfd, "/******************************************************************************\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "* Paramètres : raw = données brutes à analyser. *\n"); + dprintf(cfd, "* *\n"); + dprintf(cfd, "* Description : Décode une forme d'instruction de type '%s'.", coder->ins); + + maxlen = 20 - strlen(coder->ins); + + if (maxlen < 20) + 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 (1 /* TODO : si pas exportée */) + dprintf(cfd, "static "); + + dprintf(cfd, "GArchInstruction *"); + write_read_function_name(cfd, arch, enc_name, name); + dprintf(cfd, "_%s", prefix); + + dprintf(cfd, "("); + dprintf(cfd, "uint%u_t raw", wide); + dprintf(cfd, ")"); + + dprintf(cfd, "\n"); + dprintf(cfd, "{"); + dprintf(cfd, "\n"); + + result = write_encoding_spec_raw_disass(encoding, cfd, arch, coder->id, coder->pp); + + dprintf(cfd, "}\n"); + dprintf(cfd, "\n"); + + /* Conclusion */ + + free(prefix); + + free(name); + + free(arch); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion automatique de l'écriture de code. * +* info = précisions quant à la génération. * +* enc_name = désignation du type d'encodage visé. * +* hfd = flux ouvert en écriture pour les déclarations. * +* cfd = flux ouvert en écriture pour les définitions. * +* * +* Description : Génère ou complète un fichier contenant le code C principal. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool output_coder_main_raw(const rented_coder *coder, const output_info *info, const string_exch *enc_name, int hfd, int cfd) +{ + bool result; /* Bilan à retourner */ + char *arch; /* Architecture à traiter */ + char *name; /* Désignation à manipuler */ + unsigned int wide; /* Taille des mots */ + size_t maxlen; /* Taille à compléter */ + bool first; /* Note un premier appel */ + size_t i; /* Boucle de parcours */ + char *prefix; /* Préfixe employé en suffixe */ + + result = false; + + arch = strdup(info->arch_cn); + make_string_lower(arch); + + name = get_coder_code_name(coder); + + wide = get_bit_width_for_encoding_spec(coder, enc_name); /* Désassemblage : déclaration */ dprintf(hfd, "/* Décode une instruction de type '%s'. */\n", coder->ins); - dprintf(hfd, "GArchInstruction *%s_read_%sinstr_%s%s(uint%u_t);\n", - coder->arch, encoding->dest, keyword, coder->details, wide); + + dprintf(hfd, "GArchInstruction *"); + write_read_function_name(hfd, arch, enc_name, name); + + dprintf(hfd, "("); + dprintf(hfd, "uint%u_t raw", wide); + dprintf(hfd, ");\n"); + dprintf(hfd, "\n"); /* Désassemblage : définitions */ - dprintf(cfd, "\n"); - dprintf(cfd, "/******************************************************************************\n"); dprintf(cfd, "* *\n"); dprintf(cfd, "* Paramètres : raw = données brutes à analyser. *\n"); @@ -1006,7 +1296,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st else dprintf(cfd, "*\n"); - 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"); @@ -1015,27 +1305,55 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st dprintf(cfd, "\n"); - dprintf(cfd, "GArchInstruction *%s_read_%sinstr_%s%s(uint%u_t raw)", - coder->arch, encoding->dest, keyword, coder->details, wide); + dprintf(cfd, "GArchInstruction *"); + write_read_function_name(cfd, arch, enc_name, name); + + dprintf(cfd, "("); + dprintf(cfd, "uint%u_t raw", wide); + dprintf(cfd, ")"); + dprintf(cfd, "\n"); dprintf(cfd, "{"); dprintf(cfd, "\n"); dprintf(cfd, "\tGArchInstruction *result; /* Instruction créée à renvoyer*/\n"); - - dprintf(cfd, "\n"); - dprintf(cfd, "\tresult = NULL;\n"); dprintf(cfd, "\n"); - for (i = 0; i < coder->specs_count && result; i++) - { - spec = coder->specs[i]; + first = true; - if (!has_encoding_spec_prefix(spec, encoding->src)) + for (i = 0; i < coder->specs_count; i++) + { + if (!has_encoding_spec_prefix(coder->specs[i], enc_name->src)) continue; - result = write_encoding_spec_disass(spec, cfd, coder->arch, encoding->dest, - coder->ins, coder->details, wide, coder->pp); + result = true; + + prefix = build_encoding_spec_prefix(coder->specs[i]); + + if (first) + { + dprintf(cfd, "\tresult = "); + write_read_function_name(cfd, arch, enc_name, name); + dprintf(cfd, "_%s(raw);\n", prefix); + + dprintf(cfd, "\n"); + + first = false; + + } + else + { + dprintf(cfd, "\tif (result == NULL)\n"); + + dprintf(cfd, "\t\tresult = "); + write_read_function_name(cfd, arch, enc_name, name); + dprintf(cfd, "_%s(raw);\n", prefix); + + dprintf(cfd, "\n"); + + } + + free(prefix); } @@ -1045,7 +1363,11 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st dprintf(cfd, "}\n"); dprintf(cfd, "\n"); - free(keyword); + /* Conclusion */ + + free(name); + + free(arch); return result; @@ -1054,12 +1376,14 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st /****************************************************************************** * * -* Paramètres : coder = gestion par la machine en remplacement d'humain. * +* Paramètres : coder = gestion automatique de l'écriture de code. * +* info = précisions quant à la génération. * +* enc_name = désignation du type d'encodage visé. * * 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. * +* Description : Génère ou complète un fichier contenant le code C principal. * * * * Retour : Bilan de l'opération. * * * @@ -1067,25 +1391,24 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st * * ******************************************************************************/ -static bool dump_all_matching_specs_from_format(const rented_coder *coder, const string_exch *encoding, int hfd, int cfd) +static bool output_coder_format(const rented_coder *coder, const output_info *info, const string_exch *enc_name, const encoding_spec *encoding, int hfd, int cfd) { bool result; /* Bilan à retourner */ - char *keyword; /* Mot clef appelable en code */ + char *arch; /* Architecture à traiter */ + char *name; /* Désignation à manipuler */ size_t maxlen; /* Taille à compléter */ - encoding_spec *spec; /* Définition à traiter */ - keyword = make_callable(coder->ins, false); + arch = strdup(info->arch_cn); + make_string_lower(arch); + + name = get_coder_code_name(coder); /* 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, "GArchInstruction *"); + write_read_function_name(hfd, arch, enc_name, name); dprintf(hfd, "("); dprintf(hfd, "const GArchProcessor *, GProcContext *, const GBinContent *, "); @@ -1096,8 +1419,6 @@ static bool dump_all_matching_specs_from_format(const rented_coder *coder, const /* 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"); @@ -1115,7 +1436,7 @@ static bool dump_all_matching_specs_from_format(const rented_coder *coder, const else dprintf(cfd, "*\n"); - 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"); @@ -1124,12 +1445,8 @@ static bool dump_all_matching_specs_from_format(const rented_coder *coder, const 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, "GArchInstruction *"); + write_read_function_name(cfd, arch, enc_name, name); dprintf(cfd, "("); dprintf(cfd, "const GArchProcessor *proc, GProcContext *ctx, const GBinContent *content, "); @@ -1140,20 +1457,523 @@ static bool dump_all_matching_specs_from_format(const rented_coder *coder, const dprintf(cfd, "{"); dprintf(cfd, "\n"); - assert(coder->specs_count == 1); + result = write_encoding_spec_format_disass(encoding, cfd, arch, coder->id, info->fmt_prefix); - spec = coder->specs[0]; + dprintf(cfd, "}\n"); + dprintf(cfd, "\n"); - assert(has_encoding_spec_prefix(spec, encoding->src)); + /* Conclusion */ - result = write_encoding_spec_format_disass(spec, cfd, coder->arch, encoding->dest, - coder->ins, coder->separator, coder->raw_details, - coder->pp, coder->const_prefix); + free(name); - dprintf(cfd, "}\n"); - dprintf(cfd, "\n"); + free(arch); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pathname = chemin d'accès au fichier à traiter. * +* info = précisions quant à la génération. * +* * +* Description : Finalise le contenu utile du fichier des instructions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fini_coder_opcodes_file(const char *pathname, const output_info *info) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ouvert en écriture */ + char *temp; /* Zone de travail temporaire */ + char *base; /* Identification de fichier */ + + result = false; + + fd = open(pathname, O_WRONLY | O_APPEND, 0644); + if (fd == -1) + { + perror("open()"); + goto fcif_exit; + } + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + temp = strdup(pathname); + base = basename(temp); + + base[strlen(base) - 2] = '\0'; + + make_string_upper(base); + + dprintf(fd, "#endif /* _%s_%s_H */\n", info->guard, base); + + free(temp); + + result = true; + + fcif_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* * +* Description : Initialise le contenu utile du fichier des identifiants. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_coder_identifiers_file(int fd, const output_info *info) +{ + dprintf(fd, "#ifndef _%s_IDENTIFIERS_H\n", info->guard); + dprintf(fd, "#define _%s_IDENTIFIERS_H\n", info->guard); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + dprintf(fd, "/* Enumération de tous les opcodes */\n"); + dprintf(fd, "typedef enum _%sOpcodes\n", info->arch_cn); + dprintf(fd, "{\n"); + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * +* * +* Description : Génère ou complète un fichier constituant les identifiants. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool output_coder_identifier(const rented_coder *coder, const output_info *info) +{ + bool result; /* Bilan à retourner */ + bool created; /* Note une création */ + int fd; /* Flux ouvert en écriture */ + char *name; /* Désignation à manipuler */ + instr_id *id; /* Gestionnaire d'identifiant */ + unsigned int iid; /* Identifiant unique attribué */ + char *constant; /* Définition d'une constante */ + char *comment; /* Contenu du commentaire */ + + result = false; + + /* Ouverture de la destination */ + + fd = open_global_header_file(coder, info, "identifiers", &created); + if (fd == -1) goto oci_exit; + + if (created) + { + write_header_file_license(fd, info, "identifiers", "définition des identifiants uniques pour"); + init_coder_identifiers_file(fd, info); + } + + /* Constitution de la constante */ + + name = get_coder_code_name(coder); + make_string_upper(name); + + asprintf(&constant, "%s_%s,", info->id_prefix, name); + + free(name); + + /* Définition du commentaire */ + + name = get_coder_nominal_name(coder); + + id = get_coder_instruction_id(coder); + iid = get_instruction_id_value(id); + + asprintf(&comment, "%s (0x%0*x)", name, info->id_len, iid); + + free(name); + + /* Impression de la ligne */ + + dprintf(fd, " %-40s/* %-28s*/\n", constant, comment); + + free(constant); + free(comment); + + result = true; + + oci_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pathname = chemin d'accès au fichier à traiter. * +* info = précisions quant à la génération. * +* * +* Description : Finalise le contenu utile du fichier des identifiants. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fini_coder_identifiers_file(const char *pathname, const output_info *info) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ouvert en écriture */ + + result = false; + + fd = open(pathname, O_WRONLY | O_APPEND, 0644); + if (fd == -1) + { + perror("open()"); + goto fcif_exit; + } + + dprintf(fd, "\n"); + dprintf(fd, " %s_COUNT\n", info->id_prefix); + dprintf(fd, "\n"); + + dprintf(fd, "} %sOpcodes;\n", info->arch_cn); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + dprintf(fd, "#endif /* _%s_IDENTIFIERS_H */\n", info->guard); + + result = true; + + fcif_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* * +* Description : Initialise le contenu utile du fichier des mots clefs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_coder_keywords_file(int fd, const output_info *info) +{ + char *larch; /* Architecture en minuscules */ + + dprintf(fd, "#ifndef _%s_KEYWORDS_H\n", info->guard); + dprintf(fd, "#define _%s_KEYWORDS_H\n", info->guard); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "#include \"identifiers.h\"\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + larch = strdup(info->arch_cn); + make_string_lower(larch); + + dprintf(fd, "/* Enumération de tous les mots clefs */\n"); + dprintf(fd, "static char *_%s_keywords[%s_COUNT] = {\n", larch, info->id_prefix); + dprintf(fd, "\n"); + + free(larch); + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * +* * +* Description : Génère ou complète un fichier constituant les mots clefs. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool output_coder_keyword(const rented_coder *coder, const output_info *info) +{ + bool result; /* Bilan à retourner */ + bool created; /* Note une création */ + int fd; /* Flux ouvert en écriture */ + char *name; /* Désignation à manipuler */ + + result = false; + + /* S'il n'y a pas lieu de traiter l'instruction */ + + if (coder->useless) + { + result = true; + goto ock_exit; + } + + /* Ouverture de la destination */ + + fd = open_global_header_file(coder, info, "keywords", &created); + if (fd == -1) goto ock_exit; + + if (created) + { + write_header_file_license(fd, info, "keywords", "définition des mots clefs des instructions"); + init_coder_keywords_file(fd, info); + } + + /* Impression de la colonne */ + + name = get_coder_code_name(coder); + make_string_upper(name); + + dprintf(fd, "\t[%s_%s] = ", info->id_prefix, name); + + free(name); + + /* Impression du mot clef */ + + name = get_coder_nominal_name(coder); + + dprintf(fd, "\"%s\",\n", name); + + free(name); + + result = true; + + ock_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pathname = chemin d'accès au fichier à traiter. * +* info = précisions quant à la génération. * +* * +* Description : Finalise le contenu utile du fichier des mots clefs. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fini_coder_keywords_file(const char *pathname, const output_info *info) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ouvert en écriture */ + + result = false; + + fd = open(pathname, O_WRONLY | O_APPEND, 0644); + if (fd == -1) + { + perror("open()"); + goto fckf_exit; + } + + dprintf(fd, "\n"); + dprintf(fd, "};\n"); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + dprintf(fd, "#endif /* _%s_KEYWORDS_H */\n", info->guard); + + result = true; + + fckf_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : fd = flux ouvert en écriture mis à disposition. * +* info = précisions quant à la génération. * +* * +* Description : Initialise le contenu utile du fichier des descriptions. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void init_coder_descriptions_file(int fd, const output_info *info) +{ + char *larch; /* Architecture en minuscules */ + + dprintf(fd, "#ifndef _%s_DESCRIPTIONS_H\n", info->guard); + dprintf(fd, "#define _%s_DESCRIPTIONS_H\n", info->guard); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "#include \"identifiers.h\"\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + larch = strdup(info->arch_cn); + make_string_lower(larch); + + dprintf(fd, "/* Enumération de tous les mots clefs */\n"); + dprintf(fd, "static char *_%s_descriptions[%s_COUNT] = {\n", larch, info->id_prefix); + dprintf(fd, "\n"); + + free(larch); + +} + + +/****************************************************************************** +* * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* info = précisions quant à la génération. * +* * +* Description : Génère ou complète un fichier constituant les descriptions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool output_coder_description(const rented_coder *coder, const output_info *info) +{ + bool result; /* Bilan à retourner */ + bool created; /* Note une création */ + int fd; /* Flux ouvert en écriture */ + char *name; /* Désignation à manipuler */ + + result = false; + + /* S'il n'y a pas lieu de traiter l'instruction */ + + if (coder->useless) + { + result = true; + goto ock_exit; + } + + /* Ouverture de la destination */ + + fd = open_global_header_file(coder, info, "descriptions", &created); + if (fd == -1) goto ock_exit; + + if (created) + { + write_header_file_license(fd, info, "descriptions", "définition des descriptions des instructions"); + init_coder_descriptions_file(fd, info); + } + + /* Impression de la colonne */ + + name = get_coder_code_name(coder); + make_string_upper(name); + + dprintf(fd, "\t[%s_%s] = ", info->id_prefix, name); + + free(name); + + /* Impression du mot clef */ + + name = get_coder_nominal_name(coder); + + dprintf(fd, "\""); + + write_instruction_description(coder->desc, fd); + + dprintf(fd, "\",\n"); + + free(name); + + result = true; + + ock_exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : pathname = chemin d'accès au fichier à traiter. * +* info = précisions quant à la génération. * +* * +* Description : Finalise le contenu utile du fichier des descriptions. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool fini_coder_descriptions_file(const char *pathname, const output_info *info) +{ + bool result; /* Bilan à retourner */ + int fd; /* Flux ouvert en écriture */ + + result = false; + + fd = open(pathname, O_WRONLY | O_APPEND, 0644); + if (fd == -1) + { + perror("open()"); + goto fckf_exit; + } + + dprintf(fd, "\n"); + dprintf(fd, "};\n"); + + dprintf(fd, "\n"); + dprintf(fd, "\n"); + dprintf(fd, "\n"); + + dprintf(fd, "#endif /* _%s_DESCRIPTIONS_H */\n", info->guard); + + result = true; - free(keyword); + fckf_exit: return result; |