summaryrefslogtreecommitdiff
path: root/tools/coder.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/coder.c')
-rw-r--r--tools/coder.c1306
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;
-
-}