diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2014-11-14 19:22:25 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2014-11-14 19:22:25 (GMT) |
commit | 44e6aa9039585ad95fb9c6f21535d89457563297 (patch) | |
tree | a613aec315c32dcd83be426c31eb1bffc76ee657 /tools/coder.c | |
parent | 8056807369571b593b25fad926daa6a447d757fa (diff) |
Rewritten and extended the whole code for the instructions definitions compiler.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@419 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'tools/coder.c')
-rw-r--r-- | tools/coder.c | 1306 |
1 files changed, 39 insertions, 1267 deletions
diff --git a/tools/coder.c b/tools/coder.c index 3606bea..5856d80 100644 --- a/tools/coder.c +++ b/tools/coder.c @@ -25,32 +25,23 @@ #include <assert.h> -#include <ctype.h> #include <fcntl.h> -#include <inttypes.h> #include <malloc.h> #include <regex.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <unistd.h> -#include <sys/param.h> +#include "helpers.h" -/* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */ -/* Conversion des chaînes en chaînes */ -typedef struct _string_exch -{ - const char *src; /* Chaîne à trouver */ - const char *dest; /* Chaîne de remplacement */ +/* -------------------------- CONSTRUCTION SELON COMMANDES -------------------------- */ -} string_exch; -struct _encoding_spec; /* Suivi des constructions */ @@ -60,89 +51,24 @@ struct _rented_coder const char *arch; /* Architecture à traiter */ const char *header; /* En-tête pour les en-têtes */ - string_exch *macros; /* Remplacements de chaînes */ - size_t macros_count; /* Nombre de ces remplacements */ - - string_exch *encodings; /* Traductions d'encodages */ - size_t encodings_count; /* Nombre de ces traductions */ + pre_processor *pp; /* Pré-processeur avec macros */ char *copyright; /* Récupération des droits */ char *ins; /* Désignation humaine */ char *details; /* Eventuels compléments */ - struct _encoding_spec *specs; /* Définitions déjà en place */ + encoding_spec **specs; /* Définitions déjà en place */ size_t specs_count; /* Nombre de ces définitions */ - struct _encoding_spec *cur_spec; /* Définition courante */ + encoding_spec *cur_spec; /* Définition courante */ }; -/* Recherche l'existence d'une macro pour un remplacement. */ -static const char *find_macro_in_coder(const rented_coder *, const char *); - /* --------------------------- REPRESENTATION D'ENCODAGES --------------------------- */ -struct _dec_bitfield; -struct _syntax_item; -struct _conv_func; -struct _extra_rule; - - -/* Mémorisation d'un encodage complet */ -typedef struct _encoding_spec -{ - char *prefix; /* Distinction principale */ - unsigned int index; /* Distinction secondaire */ - - struct _dec_bitfield *bitfields; /* Champs de bits détectés */ - size_t bf_count; /* Nombre de ces champs */ - uint64_t bits; /* Bits invariables */ - uint64_t mask; /* Emplacement de ces bits */ - unsigned int curpos; /* Position pendant l'analyse */ - - struct _syntax_item *items; /* Eléments de la syntaxe */ - size_t items_count; /* Nombre de ces éléments */ - - struct _conv_func *conversions; /* Conversions des données */ - size_t conv_count; /* Nombre de ces conversions */ - - struct _extra_rule *rules; /* Régles supplémentaires */ - size_t rules_count; /* Nombre de ces règles */ - -} encoding_spec; - - -/* Libère de la mémoire une spécification d'encodage. */ -static void free_encoding_spec(encoding_spec *); - - - -/* ---------------------------- SYNTAXE DES INSTRUCTIONS ---------------------------- */ - - -/* Propriétés particulières pour les opérandes */ -typedef enum _SyntaxItemFlags -{ - SIF_NONE = (0 << 0), /* Aucune propriété */ - SIF_DECIMAL = (1 << 0) /* Affichage en décimal */ - -} SyntaxItemFlags; - -/* Elément défini dans une syntaxe */ -typedef struct _syntax_item -{ - char *name; /* Désignation humaine */ - bool internal; /* Enregistrement générique ? */ - SyntaxItemFlags flags; /* Propriétés supplémentaires */ - -} syntax_item; - - -/* Libère de la mémoire tous les éléments de syntaxe. */ -static void free_all_syntax_items_in_spec(encoding_spec *); @@ -161,11 +87,6 @@ typedef struct _dec_bitfield -/* Recherche un champ donné dans une définition. */ -static const dec_bitfield *find_named_field_in_spec(const encoding_spec *, const char *); - -/* Libère de la mémoire toutes les champs de bits définis. */ -static void free_all_bitfields_in_spec(encoding_spec *); @@ -182,67 +103,6 @@ typedef struct _conv_func } conv_func; -/* Libère de la mémoire toutes les conversions enregistrées. */ -static void free_all_conversion_in_spec(encoding_spec *); - -/* Recherche une fonction converrtissant une donnée brute. */ -static const conv_func *find_conversion_in_coder_spec(const encoding_spec *, const char *); - - - -/* --------------------------- CONDITIONS ET CONSEQUENCES --------------------------- */ - - -/* Expression d'une condition */ -struct _cond_expr -{ - bool is_simple; /* Sélection de champ */ - - union - { - struct - { - char *variable; /* Variable manipulée */ - CondCompType comp; /* Type de comparaison */ - char *bvalue; /* Valeur binaire comparée */ - - } simple; - - struct - { - cond_expr *a; /* Première sous-expression */ - CondOpType operator; /* Relation entre expressions */ - cond_expr *b; /* Seconde sous-expression */ - - } composed; - - }; - -}; - -/* Règles particulières */ -typedef struct _extra_rule -{ - cond_expr *expr; /* Expression de déclenchement */ - CondActionType action; /* Conséquence d'une validation*/ - char *details; /* Eventuel complément d'info. */ - -} extra_rule; - - -/* Libère de la mémoire une expression conditionnelle. */ -static void free_cond_expr(cond_expr *); - -/* Traduit en code une expression de condition. */ -static bool write_cond_expr(const encoding_spec *, int, const cond_expr *); - -/* Libère de la mémoire des règles. */ -static void free_all_coder_spec_rules(encoding_spec *); - -/* Traduit en code les éventuelles règles présentes. */ -static bool write_coder_spec_rules(const rented_coder *, int, const encoding_spec *, bool *); - - /* --------------------------- GENERATIONS DE CODE SOURCE --------------------------- */ @@ -253,23 +113,6 @@ static int create_code_file(const rented_coder *, const char *, const char *, co /* Ecrit une partie des fonctions issues des spécifications. */ static bool dump_all_matching_specs_in_coder(const rented_coder *, const string_exch *, int, int); -/* Traduit en code une sous-fonction de désassemblage. */ -static bool write_coder_spec_disass(const rented_coder *, int, const encoding_spec *, const char *, unsigned int); - - - -/* ---------------------------- MANIPULATIONS DE CHAINES ---------------------------- */ - - -/* Bascule toute une chaîne de caractères en (min|maj)uscules. */ -static char *_make_string_xxx(char *, int (* fn) (int)); - -#define make_string_lower(str) _make_string_xxx(str, tolower) -#define make_string_upper(str) _make_string_xxx(str, toupper) - -/* Traduit une chaîne en élément de fonction C. */ -static char *make_callable(const char *raw, bool); - /* ---------------------------------------------------------------------------------- */ @@ -295,7 +138,9 @@ rented_coder *create_coder(void) result = (rented_coder *)calloc(1, sizeof(rented_coder)); - result->cur_spec = (encoding_spec *)calloc(1, sizeof(encoding_spec)); + result->pp = create_pre_processor(); + + result->cur_spec = create_encoding_spec(); return result; @@ -318,11 +163,7 @@ void delete_coder(rented_coder *coder) { size_t i; /* Boucle de parcours */ - if (coder->macros != NULL) - free(coder->macros); - - if (coder->encodings != NULL) - free(coder->encodings); + delete_pre_processor(coder->pp); if (coder->ins != NULL) free(coder->ins); @@ -331,14 +172,12 @@ void delete_coder(rented_coder *coder) free(coder->details); for (i = 0; i < coder->specs_count; i++) - free_encoding_spec(&coder->specs[i]); + delete_encoding_spec(coder->specs[i]); if (coder->specs != NULL) free(coder->specs); - free_encoding_spec(coder->cur_spec); - - free(coder->cur_spec); + delete_encoding_spec(coder->cur_spec); free(coder); @@ -427,84 +266,18 @@ void set_coder_header_base(rented_coder *coder, const char *header) /****************************************************************************** * * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* src = chaîne à remplacer dans les définitions. * -* dest = chaîne de remplacement. * * * -* Description : Enregistre une correspondance en matière d'encodage. * +* Description : Fournit le pré-processeur du compilateur. * * * -* Retour : - * +* Retour : Pré-processeur à manipuler. * * * * Remarques : - * * * ******************************************************************************/ -void register_encoding_in_coder(rented_coder *coder, const char *src, const char *dest) +pre_processor *get_coder_pre_proc(const rented_coder *coder) { - string_exch *encoding; /* Traduction à conserver */ - - coder->encodings = (string_exch *)realloc(coder->encodings, ++coder->encodings_count * sizeof(string_exch)); - - encoding = &coder->encodings[coder->encodings_count - 1]; - - encoding->src = src; - encoding->dest = dest; - -} - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* src = chaîne à remplacer dans les définitions. * -* dest = chaîne de remplacement. * -* * -* Description : Constitue la matière d'un système de macros. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void define_macro_for_coder(rented_coder *coder, const char *src, const char *dest) -{ - string_exch *macro; /* Nouvelle macro à constituer */ - - coder->macros = (string_exch *)realloc(coder->macros, ++coder->macros_count * sizeof(string_exch)); - - macro = &coder->macros[coder->macros_count - 1]; - - macro->src = src; - macro->dest = dest; - -} - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* src = chaîne à remplacer dans les définitions. * -* * -* Description : Recherche l'existence d'une macro pour un remplacement. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const char *find_macro_in_coder(const rented_coder *coder, const char *src) -{ - const char *result; /* Trouvaille à renvoyer */ - size_t i; /* Boucle de parcours */ - - result = NULL; - - for (i = 0; i < coder->macros_count && result == NULL; i++) - if (strcmp(coder->macros[i].src, src) == 0) - result = coder->macros[i].dest; - - return result; + return coder->pp; } @@ -542,599 +315,29 @@ void save_notes_for_coder(rented_coder *coder, char *copy, char *ins, const char /****************************************************************************** * * * Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* prefix = distinction principale entre les définitions. * -* index = distinction secondaire entre les définitions. * -* * -* Description : Enregistre une définition supplémentaire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index) -{ - encoding_spec *spec; /* Définition à compléter */ - - spec = coder->cur_spec; - - spec->prefix = prefix; - spec->index = index; - - coder->specs = (encoding_spec *)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec)); - - coder->specs[coder->specs_count - 1] = *spec; - - memset(spec, 0, sizeof(encoding_spec)); - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage en cours de libération. * -* * -* Description : Libère de la mémoire une spécification d'encodage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_encoding_spec(encoding_spec *spec) -{ - free_all_syntax_items_in_spec(spec); - - free_all_bitfields_in_spec(spec); - - free_all_conversion_in_spec(spec); - - free_all_coder_spec_rules(spec); - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* GESTION DES CHAMPS DE BITS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* name = désignation humaine du champ remarqué. * -* length = taille du champ à mémoriser. * -* * -* Description : Note la présence d'un champ remarquable dans une définition. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_named_field_in_coder(rented_coder *coder, char *name, unsigned int length) -{ - encoding_spec *spec; /* Définition à compléter */ - dec_bitfield *field; /* Nouveau champ à constituer */ - - spec = coder->cur_spec; - - assert((spec->curpos + length) < 64); - - spec->bitfields = (dec_bitfield *)realloc(spec->bitfields, - ++spec->bf_count * sizeof(dec_bitfield)); - - field = &spec->bitfields[spec->bf_count - 1]; - - field->name = make_string_lower(name); - field->start = spec->curpos; - field->length = length; - - spec->curpos += length; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage à parcourir. * -* name = désignation humaine du champ à retrouver. * -* * -* Description : Recherche un champ donné dans une définition. * -* * -* Retour : Structure associée au champ trouvé ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const dec_bitfield *find_named_field_in_spec(const encoding_spec *spec, const char *name) -{ - dec_bitfield *result; /* Champ de bits à retourner */ - size_t i; /* Boucle de parcours */ - - result = NULL; - - for (i = 0; i < spec->bf_count && result == NULL; i++) - if (strcmp(spec->bitfields[i].name, name) == 0) - result = &spec->bitfields[i]; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* val = valeur du bit à prendre en compte. * -* * -* Description : Note la présence d'un bit invariable dans une définition. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_bit_in_coder(rented_coder *coder, int val) -{ - encoding_spec *spec; /* Définition à compléter */ - - spec = coder->cur_spec; - - assert(spec->curpos < 64); - - spec->bits |= (val ? 1 : 0) << spec->curpos; - spec->mask |= 1 << spec->curpos; - - spec->curpos++; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage en cours de libération. * -* * -* Description : Libère de la mémoire toutes les champs de bits définis. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_all_bitfields_in_spec(encoding_spec *spec) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < spec->bf_count; i++) - free(spec->bitfields[i].name); - - if (spec->bitfields != NULL) - { - free(spec->bitfields); - spec->bitfields = NULL; - } - - spec->bf_count = 0; - - spec->bits = 0; - spec->mask = 0; - - spec->curpos = 0; - -} - - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* * -* Description : Indique le nombre de bits traités. * -* * -* Retour : Quantité, positive ou nulle. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int count_coder_bits(const rented_coder *coder) -{ - return coder->cur_spec->curpos; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* SYNTAXE DES INSTRUCTIONS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement d'humain. * -* name = désignation de l'opérande dans la spécification. * -* internal = précise si l'opérand est non générique ou non. * -* * -* Description : Enregistre la présence d'un nouvel opérande. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_syntax_item_in_coder(rented_coder *coder, char *name, bool internal) -{ - encoding_spec *spec; /* Définition à compléter */ - syntax_item *item; /* Nouvelle prise en compte */ - size_t len; /* Taille du nom fourni */ - - spec = coder->cur_spec; - - spec->items = (syntax_item *)realloc(spec->items, ++spec->items_count * sizeof(syntax_item)); - - item = &spec->items[spec->items_count - 1]; - - /* Récupération des drapeaux */ - - item->flags = SIF_NONE; - - for (len = strlen(name); len > 0; len--) - switch (name[0]) - { - case '#': - item->flags |= SIF_DECIMAL; - memmove(name, name + 1, len); - break; - - default: - len = 1; - break; - - } - - item->name = make_string_lower(name); - item->internal = internal; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage en cours de libération. * -* * -* Description : Libère de la mémoire tous les éléments de syntaxe. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_all_syntax_items_in_spec(encoding_spec *spec) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < spec->items_count; i++) - free(spec->items[i].name); - - if (spec->items != NULL) - { - free(spec->items); - spec->items = NULL; - } - - spec->items_count = 0; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONVERSION DES ARGUMENTS */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* dest = désignation de la variable de destination. * -* func = nom de la fonction assurant le calcul de valeur. * -* arg = argument à fournir à cette fonction. * -* * -* Description : Enregistre la function de conversion du brut à l'utile. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void register_conversion_in_coder(rented_coder *coder, char *dest, char *func, char *arg) -{ - encoding_spec *spec; /* Définition à compléter */ - conv_func *conv; /* Nouvelle prise en compte */ - - spec = coder->cur_spec; - - spec->conversions = (conv_func *)realloc(spec->conversions, ++spec->conv_count * sizeof(conv_func)); - - conv = &spec->conversions[spec->conv_count - 1]; - - conv->dest = make_string_lower(dest); - conv->func = func; - conv->arg = make_string_lower(arg); - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage en cours de libération. * -* * -* Description : Libère de la mémoire toutes les conversions enregistrées. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_all_conversion_in_spec(encoding_spec *spec) -{ - size_t i; /* Boucle de parcours */ - conv_func *conv; /* Conversion à traiter */ - - for (i = 0; i < spec->conv_count; i++) - { - conv = &spec->conversions[i]; - - free(conv->dest); - free(conv->func); - free(conv->arg); - - } - - if (spec->conversions != NULL) - { - free(spec->conversions); - spec->conversions = NULL; - } - - spec->conv_count = 0; - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'un encodage à consulter. * -* dest = désignation d'une variable de destination. * -* * -* Description : Recherche une fonction converrtissant une donnée brute. * -* * -* Retour : Structure de conversion trouvée ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const conv_func *find_conversion_in_coder_spec(const encoding_spec *spec, const char *dest) -{ - const conv_func *result; /* Conversion à renvoyer */ - size_t i; /* Boucle de parcours */ - - result = NULL; - - for (i = 0; i < spec->conv_count && result == NULL; i++) - if (strcmp(spec->conversions[i].dest, dest) == 0) - result = &spec->conversions[i]; - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONDITIONS ET CONSEQUENCES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : variable = désignation de la variable à manipuler. * -* comp = type de comparaison à utiliser. * -* bvalue = valeur binaire à comparer. * -* * -* Description : Crée une expression conditionnelle simple. * -* * -* Retour : Structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *bvalue) -{ - cond_expr *result; /* Structure à retourner */ - - result = (cond_expr *)calloc(1, sizeof(cond_expr)); - - result->is_simple = true; - - result->simple.variable = make_string_lower(variable); - result->simple.comp = comp; - result->simple.bvalue = bvalue; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : a = première expression à intégrer. * -* operator = type de comparaison à utiliser. * -* b = second expression à intégrer. * * * -* Description : Crée une expression conditionnelle composée. * +* Description : Fournit un lien vers les spécifications courantes. * * * -* Retour : Structure mise en place. * +* Retour : Spécification en cours d'édition. * * * * Remarques : - * * * ******************************************************************************/ -cond_expr *build_composed_cond_expression(cond_expr *a, CondOpType operator, cond_expr *b) +encoding_spec *get_current_encoding_spec(const rented_coder *coder) { - cond_expr *result; /* Structure à retourner */ - - result = (cond_expr *)calloc(1, sizeof(cond_expr)); - - result->is_simple = false; - - result->composed.a = a; - result->composed.operator = operator; - result->composed.b = b; - - return result; + return coder->cur_spec; } /****************************************************************************** * * -* Paramètres : expr = représentation d'expression à traiter. * -* * -* Description : Libère de la mémoire une expression conditionnelle. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_cond_expr(cond_expr *expr) -{ - if (expr->is_simple) - { - free(expr->simple.variable); - free(expr->simple.bvalue); - } - else - { - free_cond_expr(expr->composed.a); - free_cond_expr(expr->composed.b); - } - - free(expr); - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'un encodage à consulter. * -* fd = descripteur d'un flux ouvert en écriture. * -* expr = expression simple ou composée à transposer. * -* * -* Description : Traduit en code une expression de condition. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool write_cond_expr(const encoding_spec *spec, int fd, const cond_expr *expr) -{ - bool result; /* Bilan à renvoyer */ - const dec_bitfield *bf; /* Champ de bits de définition */ - - result = true; - - dprintf(fd, "("); - - if (expr->is_simple) - { - bf = find_named_field_in_spec(spec, expr->simple.variable); - if (bf == NULL) - { - fprintf(stderr, "Error: no bitfield defined the requested variable '%s'.\n", expr->simple.variable); - result = false; - goto wce_exit; - } - - if (bf->length != strlen(expr->simple.bvalue)) - { - fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %zu).\n", - expr->simple.variable, bf->length, strlen(expr->simple.bvalue)); - result = false; - goto wce_exit; - } - - dprintf(fd, "raw_%s", expr->simple.variable); - - switch (expr->simple.comp) - { - case CCT_EQUAL: - dprintf(fd, " == "); - break; - case CCT_DIFF: - dprintf(fd, " != "); - break; - } - - dprintf(fd, "b%s", expr->simple.bvalue); - - } - else - { - result = write_cond_expr(spec, fd, expr->composed.a); - if (!result) goto wce_exit; - - switch (expr->composed.operator) - { - case COT_AND: - dprintf(fd, " && "); - break; - case COT_OR: - dprintf(fd, " || "); - break; - } - - result = write_cond_expr(spec, fd, expr->composed.b); - if (!result) goto wce_exit; - - } - - dprintf(fd, ")"); - - wce_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain.* -* expr = représentation d'expression à conserver. * -* action = conséquence associée à la règle. * -* details = éventuel complément d'informations. * +* Paramètres : coder = gestion par la machine en remplacement de l'humain. * +* prefix = distinction principale entre les définitions. * +* index = distinction secondaire entre les définitions. * * * -* Description : Ajoute une règle complète à la définition d'un codage. * +* Description : Enregistre une définition supplémentaire. * * * * Retour : - * * * @@ -1142,129 +345,18 @@ static bool write_cond_expr(const encoding_spec *spec, int fd, const cond_expr * * * ******************************************************************************/ -void add_conditional_rule_to_coder(rented_coder *coder, cond_expr *expr, CondActionType action, const char *details) +void push_encoding_spec(rented_coder *coder, char *prefix, unsigned int index) { encoding_spec *spec; /* Définition à compléter */ - extra_rule *rule; /* Nouvelle prise en compte */ spec = coder->cur_spec; - spec->rules = (extra_rule *)realloc(spec->rules, ++spec->rules_count * sizeof(extra_rule)); + define_encoding_spec_code_name(spec, prefix, index); - rule = &spec->rules[spec->rules_count - 1]; + coder->specs = (encoding_spec **)realloc(coder->specs, ++coder->specs_count * sizeof(encoding_spec *)); + coder->specs[coder->specs_count - 1] = spec; - rule->expr = expr; - rule->action = action; - rule->details = make_callable(details, false); - -} - - -/****************************************************************************** -* * -* Paramètres : spec = spécification d'encodage à traiter. * -* * -* Description : Libère de la mémoire des règles. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void free_all_coder_spec_rules(encoding_spec *spec) -{ - size_t i; /* Boucle de parcours */ - - for (i = 0; i < spec->rules_count; i++) - { - free_cond_expr(spec->rules[i].expr); - - if (spec->rules[i].details) - free(spec->rules[i].details); - - } - - if (spec->rules != NULL) - { - free(spec->rules); - spec->rules = NULL; - } - - spec->rules_count = 0; - -} - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain. * -* fd = descripteur d'un flux ouvert en écriture. * -* spec = spécification servant de base à l'opération. * -* exit = exprime le besoin d'une voie de sortie. [OUT] * -* * -* Description : Traduit en code les éventuelles règles présentes. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool write_coder_spec_rules(const rented_coder *coder, int fd, const encoding_spec *spec, bool *exit) -{ - bool result; /* Bilan à remonter */ - const extra_rule *rule; /* Règle en cours d'écriture */ - size_t i; /* Boucle de parcours */ - - result = true; - - *exit = false; - - for (i = 0; i < spec->rules_count; i++) - { - rule = &spec->rules[i]; - - dprintf(fd, "\t\tif "); - - result = write_cond_expr(spec, fd, rule->expr); - if (!result) break; - - dprintf(fd, "\n"); - dprintf(fd, "\t\t{\n"); - - switch (rule->action) - { - case CAT_SEE: - - if (rule->details == NULL) - { - fprintf(stderr, "Error: directive 'see' must provide additional details.\n"); - result = false; - goto wcsr_exit; - } - - dprintf(fd, "\t\t\tinstr = armv7_read_instr_%s", rule->details); - - /* TODO : adapter les paramètres d'appel selon le 'coder' */ - dprintf(fd, "(_raw);\n"); - - dprintf(fd, "\t\t\tgoto quick_exit;\n"); - - *exit = true; - break; - - } - - dprintf(fd, "\t\t}\n"); - - dprintf(fd, "\n"); - - } - - wcsr_exit: - - return result; + coder->cur_spec = create_encoding_spec(); } @@ -1360,7 +452,7 @@ bool dump_all_routines_using_coder(const rented_coder *coder) { bool result; /* Bilan à retourner */ size_t i; /* Boucle de parcours */ - string_exch *encoding; /* Type d'encodage visé */ + const string_exch *encoding; /* Type d'encodage visé */ bool exist; /* Présence du fichier visé ? */ int header_fd; /* Fichier de déclarations */ char *dash; /* Présence d'un tiret ? */ @@ -1369,9 +461,9 @@ bool dump_all_routines_using_coder(const rented_coder *coder) result = true; - for (i = 0; i < coder->encodings_count && result; i++) + for (i = 0; i < count_encodings(coder->pp) && result; i++) { - encoding = &coder->encodings[i]; + encoding = find_encoding(coder->pp, i); /* Fichier de déclarations */ @@ -1462,6 +554,7 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st unsigned int wide; /* Taille des mots */ size_t i; /* Boucle de parcours */ encoding_spec *spec; /* Définition à traiter */ + coding_bits *bits; /* Gestionnaire de bits */ size_t maxlen; /* Taille à compléter */ result = true; @@ -1474,12 +567,13 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st for (i = 0; i < coder->specs_count; i++) { - spec = &coder->specs[i]; + spec = coder->specs[i]; - if (strcmp(encoding->src, spec->prefix) != 0) + if (!has_encoding_spec_prefix(spec, encoding->src)) continue; - wide = spec->curpos; + bits = get_bits_in_encoding_spec(spec); + wide = count_coded_bits(bits); break; } @@ -1532,12 +626,12 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st for (i = 0; i < coder->specs_count && result; i++) { - spec = &coder->specs[i]; + spec = coder->specs[i]; - if (strcmp(encoding->src, spec->prefix) != 0) + if (!has_encoding_spec_prefix(spec, encoding->src)) continue; - result = write_coder_spec_disass(coder, cfd, spec, keyword, wide); + result = write_encoding_spec_disass(spec, cfd, coder->arch, coder->ins, coder->details, wide, coder->pp); } @@ -1554,325 +648,3 @@ static bool dump_all_matching_specs_in_coder(const rented_coder *coder, const st return result; } - - -/****************************************************************************** -* * -* Paramètres : coder = gestion par la machine en remplacement de l'humain.* -* fd = descripteur d'un flux ouvert en écriture. * -* spec = spécification servant de base à l'opération. * -* keyword = nom clef de l'instruction utilisable dans du code. * -* wide = taille des mots manipulés (en bits). * -* * -* Description : Traduit en code une sous-fonction de désassemblage. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool write_coder_spec_disass(const rented_coder *coder, int fd, const encoding_spec *spec, const char *keyword, unsigned int wide) -{ - size_t i; /* Boucle de parcours */ - dec_bitfield *bf; /* Accès confortable à un champ*/ - bool exit; /* Inclusion de sortie rapide ?*/ - syntax_item *item; /* Lien vers un opérande */ - regex_t preg; /* Expression régulière */ - int ret; /* Bilan d'une manipulation */ - const conv_func *conv; /* Moyen de conversion du brut */ - const char *callable; /* Fonction à appeler */ - bool rebuild; /* Construction complexe */ - regmatch_t pmatch[3]; /* Correspondances de chaînes */ - size_t cmplen; /* Taille de comparaison */ - char *cast; /* Macro de transtypage */ - - dprintf(fd, "\tGArchInstruction *%s_decode_%s%s_%s%u(uint%u_t _raw)\n", - coder->arch, keyword, coder->details, spec->prefix, spec->index, wide); - - dprintf(fd, "\t{\n"); - - dprintf(fd, "\t\tGArchInstruction *instr;\n"); - - /* Déclaration des champs à retrouver */ - - for (i = 0; i < spec->bf_count; i++) - dprintf(fd, "\t\tuint%u_t raw_%s;\n", wide, spec->bitfields[i].name); - - for (i = 0; i < spec->items_count; i++) - if (!spec->items[i].internal) - { - dprintf(fd, "\t\tGArchOperand *op;\n"); - break; - } - - dprintf(fd, "\n"); - - /* Vérification que le décodage est possible */ - - dprintf(fd, "\t\tif ((raw & 0x%" PRIx64 ") != 0x%" PRIx64 ") return NULL;\n", spec->mask, spec->bits); - - dprintf(fd, "\n"); - - /* Définition des champs bruts */ - - for (i = 0; i < spec->bf_count; i++) - { - bf = &spec->bitfields[i]; - dprintf(fd, "\t\traw_%s = (_raw >> %u) & 0x%llx;\n", bf->name, bf->start, (1ull << bf->length) - 1); - } - - dprintf(fd, "\n"); - - /* Inclusion des éventuelles règles */ - - if (!write_coder_spec_rules(coder, fd, spec, &exit)) - return false; - - /* Création de l'instruction en elle-même */ - - dprintf(fd, "\t\tinstr = g_%s_instruction_new(\"%s\");\n", coder->arch, coder->ins); - - dprintf(fd, "\n"); - - /* Création des opérandes */ - - bool build_arg_if_needed(const conv_func *conv) - { - - /* TODO : concaténation... */ - - return false; - - } - - ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED); - if (ret != 0) - { - fprintf(stderr, "Internal error: bad regular expression.\n"); - return false; - } - - - for (i = 0; i < spec->items_count; i++) - { - item = &spec->items[i]; - - conv = find_conversion_in_coder_spec(spec, item->name); - if (conv == NULL) - { - fprintf(stderr, "Error: expected conversion for '%s'.\n", item->name); - return false; - } - - callable = find_macro_in_coder(coder, conv->func); - if (callable == NULL) - { - fprintf(stderr, "Error: expected function to store '%s'.\n", item->name); - return false; - } - - rebuild = build_arg_if_needed(conv); - - if (item->internal) - { - ret = regexec(&preg, callable, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0); - if (ret == REG_NOMATCH) - { - fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callable); - return false; - } - - /** - * La variable de résultat est de type 'GArchInstruction', - * donc toute fonction différente de g_arch_instruction_*() attend un transtypage... - */ - - cmplen = MAX(strlen(coder->arch), pmatch[2].rm_eo - pmatch[2].rm_so); - - if (strncmp("arch", &callable[pmatch[2].rm_so], cmplen) == 0) - dprintf(fd, "\t\tif (!%s(instr, %s%s))\n", - callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg); - - else - { - cast = strndup(&callable[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so); - - cast = make_string_upper(cast); - - dprintf(fd, "\t\tif (!%s(%s(instr), %s%s))\n", - callable, cast, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg); - - free(cast); - - } - - dprintf(fd, "\t\t\tgoto bad_exit;\n"); - - } - - else - { - if (strchr(callable, '(') == NULL) - dprintf(fd, "\t\top = %s(%s%s);\n", - callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg); - else - dprintf(fd, "\t\top = %s%s%s);\n", - callable, rebuild ? "" : "raw_", rebuild ? item->name : conv->arg); - dprintf(fd, "\t\tif (op == NULL) goto bad_exit;\n"); - - dprintf(fd, "\n"); - - if (item->flags & SIF_DECIMAL) - dprintf(fd, "\t\tg_imm_operand_set_display(G_IMM_OPERAND(op), IOD_DEC);\n"); - - dprintf(fd, "\t\tg_arch_instruction_attach_extra_operand(instr, op);\n"); - - } - - dprintf(fd, "\n"); - - } - - regfree(&preg); - - /* Conclusion de la procédure */ - - if (exit) - { - dprintf(fd, "\t quick_exit:\n"); - dprintf(fd, "\n"); - } - - dprintf(fd, "\t\treturn instr;\n"); - - dprintf(fd, "\n"); - - dprintf(fd, "\t bad_exit:\n"); - - dprintf(fd, "\n"); - - dprintf(fd, "\t\tg_object_unref(G_OBJECT(instr));\n"); - dprintf(fd, "\t\treturn NULL;\n"); - - dprintf(fd, "\n"); - - dprintf(fd, "\t}\n"); - - dprintf(fd, "\n"); - - dprintf(fd, "\tif (result == NULL)\n"); - dprintf(fd, "\t\tresult = %s_decode_%s%s_%s%u(raw);\n", - coder->arch, keyword, coder->details, spec->prefix, spec->index); - - dprintf(fd, "\n"); - - return true; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATIONS DE CHAINES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : str = chaîne de caractères à manipuler. [OUT] * -* * -* Description : Bascule toute une chaîne de caractères en (min|maj)uscules. * -* * -* Retour : Pointeur sur la chaîne fournie. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *_make_string_xxx(char *str, int (* fn) (int)) -{ - size_t max; /* Empleur du parcours */ - size_t i; /* Boucle de parcours */ - - max = strlen(str); - - for (i = 0; i < max; i++) - str[i] = fn(str[i]); - - return str; - -} - - -/****************************************************************************** -* * -* Paramètres : raw = données brutes en provenance de l'analyseur. * -* details = indique la nature de la chaîne à traiter. * -* * -* Description : Traduit une chaîne en élément de fonction C. * -* * -* Retour : Chaîne à libérer de la mémoire après usage. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *make_callable(const char *raw, bool details) -{ - char *result; /* Nom formaté à retourner */ - size_t max; /* Empleur du parcours */ - size_t i; /* Boucle de parcours */ - - result = strdup(raw); - - max = strlen(result); - - /* Première passe : on vire les virgules */ - - for (i = 0; i < max; i++) - if (result[i] == ',') - { - memmove(result + i, result + i + 1, max - i - 1); - max--; - } - - result[max] = '\0'; - - /* Deuxième passe : on bascule en minuscules */ - - result = make_string_lower(result); - - /* Troisième passe : on remplace les mauvais caractères */ - - for (i = 0; i < max; i++) - switch (result[i]) - { - case 'a' ... 'z': - case '0' ... '9': - break; - case '-': - result[i] = '_'; - break; - default: - result[i] = (i + 1 == max ? '\0' : '_'); - break; - } - - /** - * Dernière passe : on s'assure que le premier caractère n'est pas une lettre. - * On ajoute ici le préfixe '_' utilisé lors de la génération de prototypes ; - * en cas d'absence de détails, on ne se retrouve ainsi pas avec un '_' isolé. - */ - - if (details && result[0] != '_') - { - max = strlen(result) + 1; - result = (char *)realloc(result, max); - memmove(result + 1, result, max - 1); - result[0] = '_'; - } - - return result; - -} |