summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2015-01-24 11:19:32 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2015-01-24 11:19:32 (GMT)
commit141d2f0fbb2ce3b4ddf85383c55b891fd59dc598 (patch)
tree085fa1a20d77f86825e1a6f4215b1ffd8fd961e8 /tools
parent3df9f6dc8548b0562312036abfbfcf9850a81041 (diff)
Introduced conditional calls in instruction definition rules.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@459 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'tools')
-rw-r--r--tools/d2c/Makefile.am2
-rw-r--r--tools/d2c/args.c1161
-rw-r--r--tools/d2c/args.h131
-rw-r--r--tools/d2c/conv.c1209
-rw-r--r--tools/d2c/conv.h98
-rw-r--r--tools/d2c/d2c_gram.y69
-rw-r--r--tools/d2c/d2c_tok.l51
-rw-r--r--tools/d2c/qckcall.c110
-rw-r--r--tools/d2c/qckcall.h44
-rw-r--r--tools/d2c/rules.c96
-rw-r--r--tools/d2c/rules.h32
-rw-r--r--tools/d2c/spec.c13
12 files changed, 1690 insertions, 1326 deletions
diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am
index e997beb..63ca5fe 100644
--- a/tools/d2c/Makefile.am
+++ b/tools/d2c/Makefile.am
@@ -7,6 +7,7 @@ bin_PROGRAMS = d2c
d2c_SOURCES = \
+ args.h args.c \
bits.h bits.c \
coder.h coder.c \
conv.h conv.c \
@@ -15,6 +16,7 @@ d2c_SOURCES = \
helpers.h helpers.c \
hooks.h hooks.c \
pproc.h pproc.c \
+ qckcall.h qckcall.c \
rules.h rules.c \
spec.h spec.c \
syntax.h syntax.c
diff --git a/tools/d2c/args.c b/tools/d2c/args.c
new file mode 100644
index 0000000..616873b
--- /dev/null
+++ b/tools/d2c/args.c
@@ -0,0 +1,1161 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * args.c - gestion des arguments dans leur ensemble
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "args.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "conv.h"
+#include "helpers.h"
+
+
+
+/*
+#include <assert.h>
+#include <ctype.h>
+
+#include <regex.h>
+#include <stdbool.h>
+#include <sys/param.h>
+
+
+*/
+
+
+
+
+/* Types d'expressions représentés */
+typedef enum _ConvExprType
+{
+ CET_NAME, /* Désignation de variable */
+ CET_NUMBER, /* Valeur codée en dur */
+ CET_COMPOSED, /* Agrégat de champs divers */
+ CET_UNARY, /* Opération unaire */
+ CET_BINARY, /* Opération binaire */
+
+ CET_COUNT
+
+} ConvExprType;
+
+
+/* Représentation d'une expression de conversion */
+struct _arg_expr_t
+{
+ ConvExprType type;
+
+ bool declared; /* Expression déjà déclarée ? */
+ bool defined; /* Expression déjà définie ? */
+
+ union
+ {
+ /* CET_NAME */
+ char *name; /* Désignation de variable */
+
+ /* CET_NUMBER */
+ unsigned long number; /* Valeur durablement définie */
+
+ /* CET_COMPOSED */
+ struct
+ {
+ char **comp_items; /* Elements à agréger */
+ size_t comp_count; /* Quantité de ces éléments */
+ };
+
+ /* CET_UNARY */
+ struct
+ {
+ arg_expr_t *un_expr; /* Expression à traiter */
+ ConvUnaryOperation un_op; /* Type d'opération à mener */
+
+ };
+
+ /* CET_BINARY */
+ struct
+ {
+ arg_expr_t *bin_expr1; /* Expression à traiter */
+ arg_expr_t *bin_expr2; /* Expression à traiter */
+ ConvBinaryOperation bin_op; /* Type d'opération à mener */
+
+ };
+
+ };
+
+};
+
+
+/* Visite une expression en traitant en premier ses composantes. */
+typedef bool (* visit_expr_fc) (arg_expr_t *, int, const coding_bits *, const conv_list *, void *);
+
+/* Visite une expression en traitant en premier ses composantes. */
+static bool visit_arg_expr(arg_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *);
+
+/* Retrouve si elle existe une variable manipulée. */
+static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **);
+
+
+
+/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+struct _arg_list_t
+{
+ arg_expr_t **items; /* Liste d'expressions */
+ size_t count; /* Taille de cette liste */
+
+};
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* REPRESENTATION D'UN ARGUMENT */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : name = désignation d'une variable quelconque. *
+* *
+* Description : Référence une variable en tant qu'expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *build_arg_expr_from_name(char *name)
+{
+ arg_expr_t *result; /* Structure à retourner */
+
+ result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+ result->type = CET_NAME;
+
+ result->name = make_string_lower(name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : number = valeur à conserver dans sa forme brute. *
+* *
+* Description : Conserve une valeur en tant qu'expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *build_arg_expr_from_number(unsigned long number)
+{
+ arg_expr_t *result; /* Structure à retourner */
+
+ result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+ result->type = CET_NUMBER;
+
+ result->number = number;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item1 = premier élément à agréger. *
+* item2 = second élément à agréger. *
+* *
+* Description : Construit une base d'expression de conversion composée. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *build_composed_arg_expr(char *item1, char *item2)
+{
+ arg_expr_t *result; /* Structure à retourner */
+
+ result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+ result->type = CET_COMPOSED;
+
+ result->comp_items = (char **)calloc(2, sizeof(char *));
+ result->comp_count = 2;
+
+ result->comp_items[0] = make_string_lower(item1);
+ result->comp_items[1] = make_string_lower(item2);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression déjà en place à compléter. *
+* item = nouvel élément à agréger. *
+* *
+* Description : Etend une base d'expression de conversion composée. *
+* *
+* Retour : Expression en place et mise à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *extend_composed_arg_expr(arg_expr_t *expr, char *item)
+{
+ assert(expr->type == CET_COMPOSED);
+
+ expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *));
+
+ expr->comp_items[expr->comp_count - 1] = make_string_lower(item);
+
+ return expr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à encapsuler. *
+* op = opération unaire à associer à l'opération. *
+* *
+* Description : Traduit une opération unaire sur expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *build_unary_arg_expr(arg_expr_t *expr, ConvUnaryOperation op)
+{
+ arg_expr_t *result; /* Structure à retourner */
+
+ result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+ result->type = CET_UNARY;
+
+ result->un_expr = expr;
+ result->un_op = op;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr1 = première expression à encapsuler. *
+* expr2 = seconde expression à encapsuler. *
+* op = opération binaire à associer à l'opération. *
+* *
+* Description : Traduit une opération binaire sur expression de conversion. *
+* *
+* Retour : Nouvelle expression mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_expr_t *build_binary_arg_expr(arg_expr_t *expr1, arg_expr_t *expr2, ConvBinaryOperation op)
+{
+ arg_expr_t *result; /* Structure à retourner */
+
+ result = (arg_expr_t *)calloc(1, sizeof(arg_expr_t));
+
+ result->type = CET_BINARY;
+
+ result->bin_expr1 = expr1;
+ result->bin_expr2 = expr2;
+ result->bin_op = op;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression à libérer de la mémoire. *
+* *
+* Description : Supprime tous les éléments mis en place pour un argument. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_arg_expr(arg_expr_t *expr)
+{
+ size_t i; /* Boucle de parcours */
+
+ switch (expr->type)
+ {
+ case CET_NAME:
+ free(expr->name);
+ break;
+
+ case CET_COMPOSED:
+ for (i = 0; i < expr->comp_count; i++)
+ free(expr->comp_items[i]);
+ free(expr->comp_items);
+ break;
+
+ case CET_UNARY:
+ delete_arg_expr(expr->un_expr);
+ break;
+
+ case CET_BINARY:
+ delete_arg_expr(expr->bin_expr1);
+ delete_arg_expr(expr->bin_expr2);
+ break;
+
+ default:
+ break;
+
+ }
+
+ free(expr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à consulter. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* size = taille déterminée avec précision. [OUT] *
+* *
+* Description : Détermine la taille en bits d'une expression donnée. *
+* *
+* Retour : true si la taille a pu être déterminée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool compute_arg_expr_size(const arg_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *field; /* Eventuel champ brut associé */
+ conv_func *func; /* Eventuelle fonction liée */
+ size_t i; /* Boucle de parcours */
+ unsigned int tmp; /* Stockage temporaire */
+
+ switch (expr->type)
+ {
+ case CET_NAME:
+
+ result = find_var_by_name(bits, list, expr->name, &field, &func);
+
+ if (result)
+ {
+ if (field != NULL)
+ *size = get_raw_bitfield_length(field);
+ else
+ result = compute_conv_func_size(func, bits, list, size);
+ }
+
+ break;
+
+ case CET_COMPOSED:
+
+ result = true;
+ *size = 0;
+
+ for (i = 0; i < expr->comp_count && result; i++)
+ {
+ if (isdigit(expr->comp_items[i][0]))
+ *size += strlen(expr->comp_items[i]);
+
+ else
+ {
+ if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func))
+ result = false;
+
+ else
+ {
+ if (field != NULL)
+ *size += get_raw_bitfield_length(field);
+ else
+ {
+ result = compute_conv_func_size(func, bits, list, &tmp);
+ *size += tmp;
+ }
+ }
+
+ }
+
+ }
+
+ break;
+
+ case CET_UNARY:
+ result = compute_arg_expr_size(expr->un_expr, bits, list, size);
+ break;
+
+ case CET_BINARY:
+
+ result = compute_arg_expr_size(expr->bin_expr1, bits, list, &tmp);
+
+ if (result)
+ result = compute_arg_expr_size(expr->bin_expr1, bits, list, size);
+
+ if (tmp > *size) *size = tmp;
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* data = éventuelle donnée à transmettre à chaque visite. *
+* *
+* Description : Visite une expression en traitant en premier ses composantes.*
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool visit_arg_expr(arg_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data)
+{
+ bool result; /* Bilan à retourner */
+
+ switch (expr->type)
+ {
+ case CET_UNARY:
+ result = visit_arg_expr(expr->un_expr, visit, fd, bits, list, data);
+ break;
+
+ case CET_BINARY:
+ result = visit_arg_expr(expr->bin_expr1, visit, fd, bits, list, data);
+ result = visit_arg_expr(expr->bin_expr2, visit, fd, bits, list, data);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ result &= visit(expr, fd, bits, list, data);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* name = déssignation de la variable recherchée. *
+* field = éventuel élement brut de décodage. *
+* func = éventuelle fonction de conversion pour intermédiaire.*
+* *
+* Description : Retrouve si elle existe une variable manipulée. *
+* *
+* Retour : Bilan des recherches : trouvaille ou non ? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *cached_field; /* Champ, version cachée */
+ conv_func *cached_func; /* Fonction, version cachée */
+
+ cached_field = find_named_field_in_bits(bits, name);
+ result = (cached_field != NULL);
+
+ if (!result)
+ {
+ cached_func = find_named_conv_in_list(list, name);
+ result = (cached_func != NULL);
+ }
+ else
+ cached_func = NULL;
+
+ if (field != NULL) *field = cached_field;
+ if (func != NULL) *func = cached_func;
+
+ if (!result)
+ fprintf(stderr, "Variable '%s' not found!\n", name);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : S'assure du marquage des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_marked(arg_expr_t *expr, const coding_bits *bits, const conv_list *list)
+{
+ bool mark_sub_expr(arg_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ raw_bitfield *field; /* Eventuel champ brut associé */
+ conv_func *func; /* Eventuelle fonction liée */
+
+ found = find_var_by_name(bts, lst, name, &field, &func);
+
+ if (found)
+ {
+ if (field != NULL)
+ mark_raw_bitfield_as_used(field);
+ else /*if (func != NULL) */
+ mark_conv_func(func, bts, lst);
+
+ printf(" VAR '%s' found (bf=%d fc=%d)\n", name, !!field, !!func);
+
+
+ }
+ else printf(" VAR '%s' not found...\n", name);
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = mark_by_name(bits, lst, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = mark_by_name(bits, lst, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ return result;
+
+ }
+
+ return visit_arg_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : S'assure de la déclaration des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_declared(arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool declare_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+ printf(" sub declared ? %d -- type = %d\n", sub->declared, sub->type);
+ if (sub->declared) return true;
+
+ bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ conv_func *func; /* Eventuelle fonction liée */
+
+ found = find_var_by_name(bts, lst, name, NULL, &func);
+
+ if (found && func != NULL)
+ {
+ printf("========= DECLARE for '%s'\n", name);
+ found = declare_conv_func(func, _f, _bts, _lst, _wide);
+ printf("========= END DECLARE for '%s'\n", name);
+
+ /**
+ * Si on déclare les variables suivantes dans declare_conv_func(),
+ * elles seront également déclarées pour les fonctions de conversion
+ * racine à partir de declare_syntax_items(), ce qui ne convient pas
+ * car les appels racine servent directement d'arguments.
+ */
+
+ if (is_conv_func_expression(func))
+ dprintf(_f, "\t\tuint%u_t val_%s; // Ho\n", _wide, name);
+ else
+ dprintf(_f, "\t\tGArchOperand *val_%s;;;;;\n", name);
+
+ }
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = declare_by_name(f, bits, lst, *wide, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ printf("... trying to declare... '%s'\n", sub->comp_items[i]);
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ sub->declared = result;
+
+ return result;
+
+ }
+
+ return visit_arg_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : S'assure de la définition des expressions pre-requises. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_expr_content_fully_defined(arg_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ typedef struct _def_info
+ {
+ const char *arch;
+ const pre_processor *pp;
+
+ } def_info;
+
+ def_info info; /* Transmissions au visiteur */
+
+ bool define_sub_expr(arg_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info)
+ {
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ /* Si l'expression a déjà été définie lors d'un précédent besoin... */
+ if (sub->defined) return true;
+
+ bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name)
+ {
+ bool found; /* Bilan d'opération à renvoyer*/
+ conv_func *func; /* Eventuelle fonction liée */
+
+ found = find_var_by_name(bts, lst, name, NULL, &func);
+
+ if (found && func != NULL)
+ found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp);
+
+ return found;
+
+ }
+
+ /* Il est uniquement nécessaire de s'attacher aux références */
+ switch (sub->type)
+ {
+ case CET_NAME:
+ result = define_by_name(f, bits, lst, info, sub->name);
+ break;
+
+ case CET_COMPOSED:
+ result = true;
+ for (i = 0; i < sub->comp_count && result; i++)
+ if (!isdigit(sub->comp_items[i][0]))
+ result = define_by_name(f, bits, lst, info, sub->comp_items[i]);
+ break;
+
+ default:
+ result = true;
+ break;
+
+ }
+
+ sub->defined = result;
+
+ return result;
+
+ }
+
+ info.arch = arch;
+ info.pp = pp;
+
+ return visit_arg_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = première expression à encapsuler. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Définit une expression utilisée dans une conversion. *
+* *
+* Retour : Bilan des traitements effectués. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_arg_expr(const arg_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à retourner */
+ raw_bitfield *field; /* Eventuel champ brut associé */
+ conv_func *func; /* Eventuelle fonction liée */
+ unsigned int max_size; /* Quantité de bits totale */
+ size_t i; /* Boucle de parcours */
+ const char *cname; /* Raccourci de confort */
+ unsigned int used_size; /* Quantité de bits utilisée */
+
+ result = true;
+
+ switch (expr->type)
+ {
+ case CET_NAME:
+
+ if (!find_var_by_name(bits, list, expr->name, &field, &func))
+ result = false;
+
+ else
+ {
+ if (field != NULL)
+ dprintf(fd, "raw_%s", expr->name);
+ else
+ dprintf(fd, "val_%s", expr->name);
+ }
+
+ break;
+
+ case CET_NUMBER:
+ dprintf(fd, "%lu", expr->number);
+ break;
+
+ case CET_COMPOSED:
+
+ result = compute_arg_expr_size(expr, bits, list, &max_size);
+
+ printf("MAX SIZE :: %u\n", max_size);
+
+ for (i = 0; i < expr->comp_count && result; i++)
+ {
+ cname = expr->comp_items[i];
+
+ if (i > 0)
+ dprintf(fd, " | ");
+
+ /* Constante binaire ? */
+ if (isdigit(cname[0]))
+ {
+ max_size -= strlen(cname);
+
+ if (max_size == 0)
+ dprintf(fd, "b%s", cname);
+ else
+ dprintf(fd, "b%s << %u", cname, max_size);
+
+ }
+
+ /* Ou variable définie ? */
+ else
+ {
+ result = find_var_by_name(bits, list, cname, &field, &func);
+
+ if (result)
+ {
+ if (field != NULL)
+ used_size = get_raw_bitfield_length(field);
+ else
+ /*result = */compute_conv_func_size(func, bits, list, &used_size);
+
+ max_size -= used_size;
+
+ if (field != NULL)
+ {
+ if (max_size == 0)
+ dprintf(fd, "raw_%s", cname);
+ else
+ dprintf(fd, "raw_%s << %u", cname, max_size);
+ }
+ else
+ {
+ if (max_size == 0)
+ dprintf(fd, "val_%s", cname);
+ else
+ dprintf(fd, "val_%s << %u", cname, max_size);
+ }
+
+ }
+
+ }
+
+ }
+
+ break;
+
+ case CET_UNARY:
+
+ switch (expr->un_op)
+ {
+ case CUO_NOT:
+ dprintf(fd, "!");
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ result &= define_arg_expr(expr->un_expr, fd, bits, list);
+
+ break;
+
+ case CET_BINARY:
+
+ dprintf(fd, "(");
+
+ result = define_arg_expr(expr->bin_expr1, fd, bits, list);
+
+ switch (expr->bin_op)
+ {
+ case CBO_EOR:
+ dprintf(fd, " ^ ");
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ result &= define_arg_expr(expr->bin_expr2, fd, bits, list);
+
+ dprintf(fd, ")");
+
+ break;
+
+ default:
+ result = false;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MANIPULATION DE LISTES D'ARGUMENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression initial pour constituer une liste. *
+* *
+* Description : Crée une liste d'arguments de conversion. *
+* *
+* Retour : Nouvelle structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_list_t *build_arg_list(arg_expr_t *expr)
+{
+ arg_list_t *result; /* Structure à retourner */
+
+ result = (arg_list_t *)calloc(1, sizeof(arg_list_t));
+
+ result->items = (arg_expr_t **)calloc(1, sizeof(arg_expr_t *));
+ result->count = 1;
+
+ result->items[0] = expr;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste d'expressions à supprimer de la mémoire. *
+* *
+* Description : Libère la mémoire occupée par une liste d'expressions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void delete_arg_list(arg_list_t *list)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < list->count; i++)
+ delete_arg_expr(list->items[i]);
+
+ if (list->items != NULL)
+ free(list->items);
+
+ free(list);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] *
+* expr = expression à ajouter à la liste courante. *
+* *
+* Description : Ajoute un élément à une liste d'arguments de conversion. *
+* *
+* Retour : Structure en place mise à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+arg_list_t *extend_arg_list(arg_list_t *list, arg_expr_t *expr)
+{
+ list->items = (arg_expr_t **)realloc(list->items, ++list->count * sizeof(arg_expr_t *));
+
+ list->items[list->count - 1] = expr;
+
+ return list;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : S'assure du marquage des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_marked(arg_list_t *args, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_arg_expr_content_fully_marked(args->items[i], bits, list);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* wide = taille des mots décodés. *
+* *
+* Description : S'assure de la déclaration des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_declared(arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_arg_expr_content_fully_declared(args->items[i], fd, bits, list, wide);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* arch = architecture visée par l'opération globale. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : S'assure de la définition des expressions pre-requises. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool ensure_arg_list_content_fully_defined(arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ result = ensure_arg_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* *
+* Description : Définit les variables associées à un appel de fonction. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool define_arg_list(const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list)
+{
+ bool result; /* Bilan à remonter */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < args->count && result; i++)
+ {
+ if (i > 0) dprintf(fd, ", ");
+ result = define_arg_expr(args->items[i], fd, bits, list);
+ }
+
+ return result;
+
+}
diff --git a/tools/d2c/args.h b/tools/d2c/args.h
new file mode 100644
index 0000000..0ad022e
--- /dev/null
+++ b/tools/d2c/args.h
@@ -0,0 +1,131 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * args.h - prototypes pour la gestion des arguments dans leur ensemble
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _TOOLS_ARGS_H
+#define _TOOLS_ARGS_H
+
+
+#include "bits.h"
+#include "pproc.h"
+
+
+/* Liste des fonctions de conversions présentes */
+typedef struct _conv_list conv_list;
+
+
+
+/* -------------------------- REPRESENTATION D'UN ARGUMENT -------------------------- */
+
+
+/* Types d'opérations unaires */
+typedef enum _ConvUnaryOperation
+{
+ CUO_NOT, /* NOT (booléen) */
+
+ CUO_COUNT
+
+} ConvUnaryOperation;
+
+/* Types d'opérations binaires */
+typedef enum _ConvBinaryOperation
+{
+ CBO_EOR, /* Ou exclusif (booléen) */
+
+ CBO_COUNT
+
+} ConvBinaryOperation;
+
+
+/* Représentation d'une expression de conversion */
+typedef struct _arg_expr_t arg_expr_t;
+
+
+/* Référence une variable en tant qu'expression de conversion. */
+arg_expr_t *build_arg_expr_from_name(char *);
+
+/* Conserve une valeur en tant qu'expression de conversion. */
+arg_expr_t *build_arg_expr_from_number(unsigned long );
+
+/* Construit une base d'expression de conversion composée. */
+arg_expr_t *build_composed_arg_expr(char *, char *);
+
+/* Etend une base d'expression de conversion composée. */
+arg_expr_t *extend_composed_arg_expr(arg_expr_t *, char *);
+
+/* Traduit une opération unaire sur expression de conversion. */
+arg_expr_t *build_unary_arg_expr(arg_expr_t *, ConvUnaryOperation);
+
+/* Traduit une opération binaire sur expression de conversion. */
+arg_expr_t *build_binary_arg_expr(arg_expr_t *, arg_expr_t *, ConvBinaryOperation);
+
+/* Supprime tous les éléments mis en place pour un argument. */
+void delete_arg_expr(arg_expr_t *);
+
+/* Détermine la taille en bits d'une expression donnée. */
+bool compute_arg_expr_size(const arg_expr_t *, const coding_bits *, const conv_list *, unsigned int *);
+
+/* S'assure du marquage des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_marked(arg_expr_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_declared(arg_expr_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+bool ensure_arg_expr_content_fully_defined(arg_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit une expression utilisée dans une conversion. */
+bool define_arg_expr(const arg_expr_t *, int, const coding_bits *, const conv_list *);
+
+
+
+/* ----------------------- MANIPULATION DE LISTES D'ARGUMENTS ----------------------- */
+
+
+/* Liste d'expressions utilisées en arguments de conversion */
+typedef struct _arg_list_t arg_list_t;
+
+
+/* Crée une liste d'arguments de conversion. */
+arg_list_t *build_arg_list(arg_expr_t *);
+
+/* Libère la mémoire occupée par une liste d'expressions. */
+void delete_arg_list(arg_list_t *);
+
+/* Ajoute un élément à une liste d'arguments de conversion. */
+arg_list_t *extend_arg_list(arg_list_t *, arg_expr_t *);
+
+/* S'assure du marquage des expressions pre-requises. */
+bool ensure_arg_list_content_fully_marked(arg_list_t *, const coding_bits *, const conv_list *);
+
+/* S'assure de la déclaration des expressions pre-requises. */
+bool ensure_arg_list_content_fully_declared(arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int);
+
+/* S'assure de la définition des expressions pre-requises. */
+bool ensure_arg_list_content_fully_defined(arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
+
+/* Définit les variables associées à un appel de fonction. */
+bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_list *);
+
+
+
+#endif /* _TOOLS_ARGS_H */
diff --git a/tools/d2c/conv.c b/tools/d2c/conv.c
index e103c93..9947593 100644
--- a/tools/d2c/conv.c
+++ b/tools/d2c/conv.c
@@ -27,127 +27,12 @@
#include <assert.h>
#include <ctype.h>
#include <malloc.h>
-#include <regex.h>
#include <stdbool.h>
#include <string.h>
-#include <sys/param.h>
#include "helpers.h"
-
-
-
-
-
-/* Types d'expressions représentés */
-typedef enum _ConvExprType
-{
- CET_NAME, /* Désignation de variable */
- CET_NUMBER, /* Valeur codée en dur */
- CET_COMPOSED, /* Agrégat de champs divers */
- CET_UNARY, /* Opération unaire */
- CET_BINARY, /* Opération binaire */
-
- CET_COUNT
-
-} ConvExprType;
-
-
-/* Représentation d'une expression de conversion */
-struct _conv_expr_t
-{
- ConvExprType type;
-
- bool declared; /* Expression déjà déclarée ? */
- bool defined; /* Expression déjà définie ? */
-
- union
- {
- /* CET_NAME */
- char *name; /* Désignation de variable */
-
- /* CET_NUMBER */
- unsigned long number; /* Valeur durablement définie */
-
- /* CET_COMPOSED */
- struct
- {
- char **comp_items; /* Elements à agréger */
- size_t comp_count; /* Quantité de ces éléments */
- };
-
- /* CET_UNARY */
- struct
- {
- conv_expr_t *un_expr; /* Expression à traiter */
- ConvUnaryOperation un_op; /* Type d'opération à mener */
-
- };
-
- /* CET_BINARY */
- struct
- {
- conv_expr_t *bin_expr1; /* Expression à traiter */
- conv_expr_t *bin_expr2; /* Expression à traiter */
- ConvBinaryOperation bin_op; /* Type d'opération à mener */
-
- };
-
- };
-
-};
-
-
-/* Visite une expression en traitant en premier ses composantes. */
-typedef bool (* visit_expr_fc) (conv_expr_t *, int, const coding_bits *, const conv_list *, void *);
-
-
-/* Détermine la taille en bits d'une expression donnée. */
-static bool compute_conv_expr_size(const conv_expr_t *, const coding_bits *, const conv_list *, unsigned int *);
-
-/* Visite une expression en traitant en premier ses composantes. */
-static bool visit_conv_expr(conv_expr_t *, visit_expr_fc, int, const coding_bits *, const conv_list *, void *);
-
-/* Retrouve si elle existe une variable manipulée. */
-static bool find_var_by_name(const coding_bits *, const conv_list *, const char *, raw_bitfield **, conv_func **);
-
-/* S'assure du marquage des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_marked(conv_expr_t *, const coding_bits *, const conv_list *);
-
-/* S'assure de la déclaration des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_declared(conv_expr_t *, int, const coding_bits *, const conv_list *, unsigned int);
-
-/* S'assure de la définition des expressions pre-requises. */
-static bool ensure_conv_expr_content_fully_defined(conv_expr_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
-
-/* Définit une expression utilisée dans une conversion. */
-static bool define_conv_expr(conv_expr_t *, int, const coding_bits *, const conv_list *);
-
-
-
-/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
-
-
-/* Liste d'expressions utilisées en arguments de conversion */
-struct _conv_arg_list_t
-{
- conv_expr_t **items; /* Liste d'expressions */
- size_t count; /* Taille de cette liste */
-
-};
-
-
-/* S'assure du marquage des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *, const coding_bits *, const conv_list *);
-
-/* S'assure de la déclaration des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *, int, const coding_bits *, const conv_list *, unsigned int);
-
-/* S'assure de la définition des expressions pre-requises. */
-static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *, int, const char *, const coding_bits *, const conv_list *, const pre_processor *);
-
-/* Définit les variables associées à un appel de fonction. */
-static bool define_arg_list(conv_arg_list_t *, int, const coding_bits *, const conv_list *);
+#include "qckcall.h"
@@ -166,12 +51,12 @@ struct _conv_func
union
{
- conv_expr_t *expr; /* Valeur expressive directe */
+ arg_expr_t *expr; /* Valeur expressive directe */
struct
{
char *name; /* Fonction de conversion */
- conv_arg_list_t *args; /* Liste des arguments */
+ arg_list_t *args; /* Liste des arguments */
};
@@ -180,20 +65,6 @@ struct _conv_func
};
-/* Détermine la taille en bits du résultat d'une fonction. */
-static bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *);
-
-
-
-
-
-
-#define delete_conv_expr(e)
-
-
-
-
-
/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
@@ -208,986 +79,6 @@ struct _conv_list
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : name = désignation d'une variable quelconque. *
-* *
-* Description : Référence une variable en tant qu'expression de conversion. *
-* *
-* Retour : Nouvelle expression mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *build_conv_expr_from_name(char *name)
-{
- conv_expr_t *result; /* Structure à retourner */
-
- result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
- result->type = CET_NAME;
-
- result->name = make_string_lower(name);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : number = valeur à conserver dans sa forme brute. *
-* *
-* Description : Conserve une valeur en tant qu'expression de conversion. *
-* *
-* Retour : Nouvelle expression mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *build_conv_expr_from_number(unsigned long number)
-{
- conv_expr_t *result; /* Structure à retourner */
-
- result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
- result->type = CET_NUMBER;
-
- result->number = number;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : item1 = premier élément à agréger. *
-* item2 = second élément à agréger. *
-* *
-* Description : Construit une base d'expression de conversion composée. *
-* *
-* Retour : Nouvelle expression mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *build_composed_conv_expr(char *item1, char *item2)
-{
- conv_expr_t *result; /* Structure à retourner */
-
- result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
- result->type = CET_COMPOSED;
-
- result->comp_items = (char **)calloc(2, sizeof(char *));
- result->comp_count = 2;
-
- result->comp_items[0] = make_string_lower(item1);
- result->comp_items[1] = make_string_lower(item2);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = expression déjà en place à compléter. *
-* item = nouvel élément à agréger. *
-* *
-* Description : Etend une base d'expression de conversion composée. *
-* *
-* Retour : Expression en place et mise à jour. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *extend_composed_conv_expr(conv_expr_t *expr, char *item)
-{
- assert(expr->type == CET_COMPOSED);
-
- expr->comp_items = (char **)realloc(expr->comp_items, ++expr->comp_count * sizeof(char *));
-
- expr->comp_items[expr->comp_count - 1] = make_string_lower(item);
-
- return expr;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = expression à encapsuler. *
-* op = opération unaire à associer à l'opération. *
-* *
-* Description : Traduit une opération unaire sur expression de conversion. *
-* *
-* Retour : Nouvelle expression mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *build_unary_conv_expr(conv_expr_t *expr, ConvUnaryOperation op)
-{
- conv_expr_t *result; /* Structure à retourner */
-
- result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
- result->type = CET_UNARY;
-
- result->un_expr = expr;
- result->un_op = op;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr1 = première expression à encapsuler. *
-* expr2 = seconde expression à encapsuler. *
-* op = opération binaire à associer à l'opération. *
-* *
-* Description : Traduit une opération binaire sur expression de conversion. *
-* *
-* Retour : Nouvelle expression mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_expr_t *build_binary_conv_expr(conv_expr_t *expr1, conv_expr_t *expr2, ConvBinaryOperation op)
-{
- conv_expr_t *result; /* Structure à retourner */
-
- result = (conv_expr_t *)calloc(1, sizeof(conv_expr_t));
-
- result->type = CET_BINARY;
-
- result->bin_expr1 = expr1;
- result->bin_expr2 = expr2;
- result->bin_op = op;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à consulter. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* size = taille déterminée avec précision. [OUT] *
-* *
-* Description : Détermine la taille en bits d'une expression donnée. *
-* *
-* Retour : true si la taille a pu être déterminée, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool compute_conv_expr_size(const conv_expr_t *expr, const coding_bits *bits, const conv_list *list, unsigned int *size)
-{
- bool result; /* Bilan à retourner */
- raw_bitfield *field; /* Eventuel champ brut associé */
- conv_func *func; /* Eventuelle fonction liée */
- size_t i; /* Boucle de parcours */
- unsigned int tmp; /* Stockage temporaire */
-
- switch (expr->type)
- {
- case CET_NAME:
-
- result = find_var_by_name(bits, list, expr->name, &field, &func);
-
- if (result)
- {
- if (field != NULL)
- *size = get_raw_bitfield_length(field);
- else
- result = compute_conv_func_size(func, bits, list, size);
- }
-
- break;
-
- case CET_COMPOSED:
-
- result = true;
- *size = 0;
-
- for (i = 0; i < expr->comp_count && result; i++)
- {
- if (isdigit(expr->comp_items[i][0]))
- *size += strlen(expr->comp_items[i]);
-
- else
- {
- if (!find_var_by_name(bits, list, expr->comp_items[i], &field, &func))
- result = false;
-
- else
- {
- if (field != NULL)
- *size += get_raw_bitfield_length(field);
- else
- {
- result = compute_conv_func_size(func, bits, list, &tmp);
- *size += tmp;
- }
- }
-
- }
-
- }
-
- break;
-
- case CET_UNARY:
- result = compute_conv_expr_size(expr->un_expr, bits, list, size);
- break;
-
- case CET_BINARY:
-
- result = compute_conv_expr_size(expr->bin_expr1, bits, list, &tmp);
-
- if (result)
- result = compute_conv_expr_size(expr->bin_expr1, bits, list, size);
-
- if (tmp > *size) *size = tmp;
-
- break;
-
- default:
- result = false;
- break;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à encapsuler. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* data = éventuelle donnée à transmettre à chaque visite. *
-* *
-* Description : Visite une expression en traitant en premier ses composantes.*
-* *
-* Retour : Bilan des traitements effectués. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool visit_conv_expr(conv_expr_t *expr, visit_expr_fc visit, int fd, const coding_bits *bits, const conv_list *list, void *data)
-{
- bool result; /* Bilan à retourner */
-
- switch (expr->type)
- {
- case CET_UNARY:
- result = visit_conv_expr(expr->un_expr, visit, fd, bits, list, data);
- break;
-
- case CET_BINARY:
- result = visit_conv_expr(expr->bin_expr1, visit, fd, bits, list, data);
- result = visit_conv_expr(expr->bin_expr2, visit, fd, bits, list, data);
- break;
-
- default:
- result = true;
- break;
-
- }
-
- result &= visit(expr, fd, bits, list, data);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* name = déssignation de la variable recherchée. *
-* field = éventuel élement brut de décodage. *
-* func = éventuelle fonction de conversion pour intermédiaire.*
-* *
-* Description : Retrouve si elle existe une variable manipulée. *
-* *
-* Retour : Bilan des recherches : trouvaille ou non ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool find_var_by_name(const coding_bits *bits, const conv_list *list, const char *name, raw_bitfield **field, conv_func **func)
-{
- bool result; /* Bilan à retourner */
- raw_bitfield *cached_field; /* Champ, version cachée */
- conv_func *cached_func; /* Fonction, version cachée */
-
- cached_field = find_named_field_in_bits(bits, name);
- result = (cached_field != NULL);
-
- if (!result)
- {
- cached_func = find_named_conv_in_list(list, name);
- result = (cached_func != NULL);
- }
- else
- cached_func = NULL;
-
- if (field != NULL) *field = cached_field;
- if (func != NULL) *func = cached_func;
-
- if (!result)
- fprintf(stderr, "Variable '%s' not found!\n", name);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à encapsuler. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* *
-* Description : S'assure du marquage des expressions pre-requises. *
-* *
-* Retour : Bilan des traitements effectués. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_marked(conv_expr_t *expr, const coding_bits *bits, const conv_list *list)
-{
- bool mark_sub_expr(conv_expr_t *sub, int dummy, const coding_bits *bts, const conv_list *lst, void *unused)
- {
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
-
- bool mark_by_name(const coding_bits *_bts, const conv_list *_lst, const char *name)
- {
- bool found; /* Bilan d'opération à renvoyer*/
- raw_bitfield *field; /* Eventuel champ brut associé */
- conv_func *func; /* Eventuelle fonction liée */
-
- found = find_var_by_name(bts, lst, name, &field, &func);
-
- if (found)
- {
- if (field != NULL)
- mark_raw_bitfield_as_used(field);
- else /*if (func != NULL) */
- mark_conv_func(func, bts, lst);
-
- printf(" VAR '%s' found (bf=%d fc=%d)\n", name, !!field, !!func);
-
-
- }
- else printf(" VAR '%s' not found...\n", name);
-
- return found;
-
- }
-
- /* Il est uniquement nécessaire de s'attacher aux références */
- switch (sub->type)
- {
- case CET_NAME:
- result = mark_by_name(bits, lst, sub->name);
- break;
-
- case CET_COMPOSED:
- result = true;
- for (i = 0; i < sub->comp_count && result; i++)
- if (!isdigit(sub->comp_items[i][0]))
- result = mark_by_name(bits, lst, sub->comp_items[i]);
- break;
-
- default:
- result = true;
- break;
-
- }
-
- return result;
-
- }
-
- return visit_conv_expr(expr, (visit_expr_fc)mark_sub_expr, -1, bits, list, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à encapsuler. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* arch = architecture visée par l'opération globale. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* wide = taille des mots décodés. *
-* *
-* Description : S'assure de la déclaration des expressions pre-requises. *
-* *
-* Retour : Bilan des traitements effectués. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_declared(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
-{
- bool declare_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, unsigned int *wide)
- {
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
-
- /* Si l'expression a déjà été définie lors d'un précédent besoin... */
- printf(" sub declared ? %d -- type = %d\n", sub->declared, sub->type);
- if (sub->declared) return true;
-
- bool declare_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, unsigned int _wide, const char *name)
- {
- bool found; /* Bilan d'opération à renvoyer*/
- conv_func *func; /* Eventuelle fonction liée */
-
- found = find_var_by_name(bts, lst, name, NULL, &func);
-
- if (found && func != NULL)
- {
- if (func->is_expr)
- dprintf(_f, "\t\tuint%u_t val_%s;\n", _wide, name);
- else
- dprintf(_f, "\t\tGArchOperand *val_%s;\n", name);
-
- printf("========= DECLARE for '%s'\n", name);
- found = declare_conv_func(func, _f, _bts, _lst, _wide);
- printf("========= END DECLARE for '%s'\n", name);
- }
-
- return found;
-
- }
-
- /* Il est uniquement nécessaire de s'attacher aux références */
- switch (sub->type)
- {
- case CET_NAME:
- result = declare_by_name(f, bits, lst, *wide, sub->name);
- break;
-
- case CET_COMPOSED:
- result = true;
- for (i = 0; i < sub->comp_count && result; i++)
- if (!isdigit(sub->comp_items[i][0]))
- printf("... trying to declare... '%s'\n", sub->comp_items[i]);
- for (i = 0; i < sub->comp_count && result; i++)
- if (!isdigit(sub->comp_items[i][0]))
- result = declare_by_name(f, bits, lst, *wide, sub->comp_items[i]);
- break;
-
- default:
- result = true;
- break;
-
- }
-
- sub->declared = result;
-
- return result;
-
- }
-
- return visit_conv_expr(expr, (visit_expr_fc)declare_sub_expr, fd, bits, list, &wide);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à encapsuler. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* arch = architecture visée par l'opération globale. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* pp = pré-processeur pour les échanges de chaînes. *
-* *
-* Description : S'assure de la définition des expressions pre-requises. *
-* *
-* Retour : Bilan des traitements effectués. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_conv_expr_content_fully_defined(conv_expr_t *expr, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
-{
- typedef struct _def_info
- {
- const char *arch;
- const pre_processor *pp;
-
- } def_info;
-
- def_info info; /* Transmissions au visiteur */
-
- bool define_sub_expr(conv_expr_t *sub, int f, const coding_bits *bts, const conv_list *lst, def_info *info)
- {
- bool result; /* Bilan à retourner */
- size_t i; /* Boucle de parcours */
-
- /* Si l'expression a déjà été définie lors d'un précédent besoin... */
- if (sub->defined) return true;
-
- bool define_by_name(int _f, const coding_bits *_bts, const conv_list *_lst, def_info *_info, const char *name)
- {
- bool found; /* Bilan d'opération à renvoyer*/
- conv_func *func; /* Eventuelle fonction liée */
-
- found = find_var_by_name(bts, lst, name, NULL, &func);
-
- if (found && func != NULL)
- found = define_conv_func(func, false, false, _f, _info->arch, _bts, _lst, _info->pp);
-
- return found;
-
- }
-
- /* Il est uniquement nécessaire de s'attacher aux références */
- switch (sub->type)
- {
- case CET_NAME:
- result = define_by_name(f, bits, lst, info, sub->name);
- break;
-
- case CET_COMPOSED:
- result = true;
- for (i = 0; i < sub->comp_count && result; i++)
- if (!isdigit(sub->comp_items[i][0]))
- result = define_by_name(f, bits, lst, info, sub->comp_items[i]);
- break;
-
- default:
- result = true;
- break;
-
- }
-
- sub->defined = result;
-
- return result;
-
- }
-
- info.arch = arch;
- info.pp = pp;
-
- return visit_conv_expr(expr, (visit_expr_fc)define_sub_expr, fd, bits, list, &info);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = première expression à encapsuler. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* *
-* Description : Définit une expression utilisée dans une conversion. *
-* *
-* Retour : Bilan des traitements effectués. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool define_conv_expr(conv_expr_t *expr, int fd, const coding_bits *bits, const conv_list *list)
-{
- bool result; /* Bilan à retourner */
- raw_bitfield *field; /* Eventuel champ brut associé */
- conv_func *func; /* Eventuelle fonction liée */
- unsigned int max_size; /* Quantité de bits totale */
- size_t i; /* Boucle de parcours */
- const char *cname; /* Raccourci de confort */
- unsigned int used_size; /* Quantité de bits utilisée */
-
- result = true;
-
- switch (expr->type)
- {
- case CET_NAME:
-
- if (!find_var_by_name(bits, list, expr->name, &field, &func))
- result = false;
-
- else
- {
- if (field != NULL)
- dprintf(fd, "raw_%s", expr->name);
- else
- dprintf(fd, "val_%s", expr->name);
- }
-
- break;
-
- case CET_NUMBER:
- dprintf(fd, "%lu", expr->number);
- break;
-
- case CET_COMPOSED:
-
- result = compute_conv_expr_size(expr, bits, list, &max_size);
-
- printf("MAX SIZE :: %u\n", max_size);
-
- for (i = 0; i < expr->comp_count && result; i++)
- {
- cname = expr->comp_items[i];
-
- if (i > 0)
- dprintf(fd, " | ");
-
- /* Constante binaire ? */
- if (isdigit(cname[0]))
- {
- max_size -= strlen(cname);
-
- if (max_size == 0)
- dprintf(fd, "b%s", cname);
- else
- dprintf(fd, "b%s << %u", cname, max_size);
-
- }
-
- /* Ou variable définie ? */
- else
- {
- result = find_var_by_name(bits, list, cname, &field, &func);
-
- if (result)
- {
- if (field != NULL)
- used_size = get_raw_bitfield_length(field);
- else
- /*result = */compute_conv_func_size(func, bits, list, &used_size);
-
- max_size -= used_size;
-
- if (field != NULL)
- {
- if (max_size == 0)
- dprintf(fd, "raw_%s", cname);
- else
- dprintf(fd, "raw_%s << %u", cname, max_size);
- }
- else
- {
- if (max_size == 0)
- dprintf(fd, "val_%s", cname);
- else
- dprintf(fd, "val_%s << %u", cname, max_size);
- }
-
- }
-
- }
-
- }
-
- break;
-
- case CET_UNARY:
-
- switch (expr->un_op)
- {
- case CUO_NOT:
- dprintf(fd, "!");
- break;
- default:
- result = false;
- break;
- }
-
- result &= define_conv_expr(expr->un_expr, fd, bits, list);
-
- break;
-
- case CET_BINARY:
-
- dprintf(fd, "(");
-
- result = define_conv_expr(expr->bin_expr1, fd, bits, list);
-
- switch (expr->bin_op)
- {
- case CBO_EOR:
- dprintf(fd, " ^ ");
- break;
- default:
- result = false;
- break;
- }
-
- result &= define_conv_expr(expr->bin_expr2, fd, bits, list);
-
- dprintf(fd, ")");
-
- break;
-
- default:
- result = false;
- break;
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* LISTES D'ARGUMENTS DE CONVERSION */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : expr = expression initial pour constituer une liste. *
-* *
-* Description : Crée une liste d'arguments de conversion. *
-* *
-* Retour : Nouvelle structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_arg_list_t *build_conv_arg_list(conv_expr_t *expr)
-{
- conv_arg_list_t *result; /* Structure à retourner */
-
- result = (conv_arg_list_t *)calloc(1, sizeof(conv_arg_list_t));
-
- result->items = (conv_expr_t **)calloc(1, sizeof(conv_expr_t *));
- result->count = 1;
-
- result->items[0] = expr;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : list = liste d'expressions à supprimer de la mémoire. *
-* *
-* Description : Libère la mémoire occupée par une liste d'expressions. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void delete_conv_arg_list(conv_arg_list_t *list)
-{
- size_t i; /* Boucle de parcours */
-
- for (i = 0; i < list->count; i++)
- delete_conv_expr(list->items[i]);
-
- if (list->items != NULL)
- free(list->items);
-
- free(list);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : list = liste d'expressions à supprimer de la mémoire. [OUT] *
-* expr = expression à ajouter à la liste courante. *
-* *
-* Description : Ajoute un élément à une liste d'arguments de conversion. *
-* *
-* Retour : Structure en place mise à jour. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *list, conv_expr_t *expr)
-{
- list->items = (conv_expr_t **)realloc(list->items, ++list->count * sizeof(conv_expr_t *));
-
- list->items[list->count - 1] = expr;
-
- return list;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* *
-* Description : S'assure du marquage des expressions pre-requises. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_arg_list_content_fully_marked(conv_arg_list_t *args, const coding_bits *bits, const conv_list *list)
-{
- bool result; /* Bilan à remonter */
- size_t i; /* Boucle de parcours */
-
- result = true;
-
- for (i = 0; i < args->count && result; i++)
- result = ensure_conv_expr_content_fully_marked(args->items[i], bits, list);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* wide = taille des mots décodés. *
-* *
-* Description : S'assure de la déclaration des expressions pre-requises. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_arg_list_content_fully_declared(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, unsigned int wide)
-{
- bool result; /* Bilan à remonter */
- size_t i; /* Boucle de parcours */
-
- result = true;
-
- for (i = 0; i < args->count && result; i++)
- result = ensure_conv_expr_content_fully_declared(args->items[i], fd, bits, list, wide);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* arch = architecture visée par l'opération globale. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* pp = pré-processeur pour les échanges de chaînes. *
-* *
-* Description : S'assure de la définition des expressions pre-requises. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool ensure_arg_list_content_fully_defined(conv_arg_list_t *args, int fd, const char *arch, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
-{
- bool result; /* Bilan à remonter */
- size_t i; /* Boucle de parcours */
-
- result = true;
-
- for (i = 0; i < args->count && result; i++)
- result = ensure_conv_expr_content_fully_defined(args->items[i], fd, arch, bits, list, pp);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : args = liste d'expressions à supprimer de la mémoire. *
-* fd = descripteur d'un flux ouvert en écriture. *
-* bits = gestionnaire des bits d'encodage. *
-* list = liste de l'ensemble des fonctions de conversion. *
-* *
-* Description : Définit les variables associées à un appel de fonction. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list)
-{
- bool result; /* Bilan à remonter */
- size_t i; /* Boucle de parcours */
-
- result = true;
-
- for (i = 0; i < args->count && result; i++)
- {
- if (i > 0) dprintf(fd, ", ");
- result = define_conv_expr(args->items[i], fd, bits, list);
- }
-
- return result;
-
-}
-
-
-
/* ---------------------------------------------------------------------------------- */
/* CONVERSION DES ARGUMENTS */
/* ---------------------------------------------------------------------------------- */
@@ -1206,7 +97,7 @@ static bool define_arg_list(conv_arg_list_t *args, int fd, const coding_bits *bi
* *
******************************************************************************/
-conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr)
+conv_func *make_conv_from_expr(char *dest, arg_expr_t *expr)
{
conv_func *result; /* Conversion à retourner */
@@ -1236,7 +127,7 @@ conv_func *make_conv_from_expr(char *dest, conv_expr_t *expr)
* *
******************************************************************************/
-conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args)
+conv_func *make_conv_from_func(char *dest, char *func, arg_list_t *args)
{
conv_func *result; /* Conversion à retourner */
@@ -1268,12 +159,12 @@ conv_func *make_conv_from_func(char *dest, char *func, conv_arg_list_t *args)
void delete_conv_func(conv_func *func)
{
if (func->is_expr)
- delete_conv_expr(func->expr);
+ delete_arg_expr(func->expr);
else
{
free(func->name);
- delete_conv_arg_list(func->args);
+ delete_arg_list(func->args);
}
free(func);
@@ -1303,6 +194,25 @@ const char *get_conv_dest_name(const conv_func *func)
/******************************************************************************
* *
* Paramètres : func = fonction de conversion à consulter. *
+* *
+* Description : Indique la nature d'une conversion : fonction ou expression ?*
+* *
+* Retour : Indication sur la constitution interne de la conversion. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool is_conv_func_expression(const conv_func *func)
+{
+ return func->is_expr;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : func = fonction de conversion à consulter. *
* bits = gestionnaire des bits d'encodage. *
* list = liste de l'ensemble des fonctions de conversion. *
* size = taille déterminée avec précision. [OUT] *
@@ -1315,14 +225,14 @@ const char *get_conv_dest_name(const conv_func *func)
* *
******************************************************************************/
-static bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size)
+bool compute_conv_func_size(const conv_func *func, const coding_bits *bits, const conv_list *list, unsigned int *size)
{
bool result; /* Bilan à retourner */
result = func->is_expr;
if (result)
- result = compute_conv_expr_size(func->expr, bits, list, size);
+ result = compute_arg_expr_size(func->expr, bits, list, size);
return result;
@@ -1348,7 +258,7 @@ bool mark_conv_func(conv_func *func, const coding_bits *bits, const conv_list *l
bool result; /* Bilan à remonter */
if (func->is_expr)
- result = ensure_conv_expr_content_fully_marked(func->expr, bits, list);
+ result = ensure_arg_expr_content_fully_marked(func->expr, bits, list);
else
result = ensure_arg_list_content_fully_marked(func->args, bits, list);
@@ -1378,11 +288,11 @@ bool declare_conv_func(conv_func *func, int fd, const coding_bits *bits, const c
bool result; /* Bilan à remonter */
/* Si la fonction a déjà été définie lors d'un précédent besoin... */
- printf(" func declared ? %d\n", func->declared);
if (func->declared) return true;
if (func->is_expr)
- result = ensure_conv_expr_content_fully_declared(func->expr, fd, bits, list, wide);
+ result = ensure_arg_expr_content_fully_declared(func->expr, fd, bits, list, wide);
+
else
result = ensure_arg_list_content_fully_declared(func->args, fd, bits, list, wide);
@@ -1416,17 +326,12 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
{
bool result; /* Bilan à remonter */
const char *callable; /* Fonction à appeler */
- regex_t preg; /* Expression régulière */
- int ret; /* Bilan d'une manipulation */
- regmatch_t pmatch[3]; /* Correspondances de chaînes */
- size_t cmplen; /* Taille de comparaison */
- char *cast; /* Macro de transtypage */
/* Si la fonction a déjà été définie lors d'un précédent besoin... */
if (func->defined) return true;
if (func->is_expr)
- result = ensure_conv_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp);
+ result = ensure_arg_expr_content_fully_defined(func->expr, fd, arch, bits, list, pp);
else
result = ensure_arg_list_content_fully_defined(func->args, fd, arch, bits, list, pp);
@@ -1453,53 +358,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
{
/* Si l'on doit manipuler une propriété d'instructon... */
if (internal)
- {
- ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
- if (ret != 0)
- {
- fprintf(stderr, "Internal error: bad regular expression.\n");
- return false;
- }
-
- 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);
- result = false;
- goto dcf_skip_internal;
- }
-
- /**
- * La variable de résultat est de type 'GArchInstruction',
- * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
- */
-
- cmplen = MAX(strlen(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, ", callable);
-
- 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), ", callable, cast);
-
- free(cast);
-
- }
-
- result &= define_arg_list(func->args, fd, bits, list);
-
- dprintf(fd, "))\n");
-
- dcf_skip_internal:
-
- regfree(&preg);
-
- }
+ result = call_instr_func(callable, func->args, fd, bits, list, pp);
/* Si on doit constituer un opérande à ajouter... */
else
@@ -1523,7 +382,7 @@ bool define_conv_func(conv_func *func, bool last, bool internal, int fd, const c
dprintf(fd, "\t\tval_%s = ", func->dest);
if (func->is_expr)
- result &= define_conv_expr(func->expr, fd, bits, list);
+ result &= define_arg_expr(func->expr, fd, bits, list);
else
{
diff --git a/tools/d2c/conv.h b/tools/d2c/conv.h
index acf007b..85c7578 100644
--- a/tools/d2c/conv.h
+++ b/tools/d2c/conv.h
@@ -25,88 +25,12 @@
#define _TOOLS_CONV_H
-#include "bits.h"
-#include "pproc.h"
-
-
-
-
-/* Liste des fonctions de conversions présentes */
-typedef struct _conv_list conv_list;
-
-
-
-
-
-
-
-/* Types d'opérations unaires */
-typedef enum _ConvUnaryOperation
-{
- CUO_NOT, /* NOT (booléen) */
-
- CUO_COUNT
-
-} ConvUnaryOperation;
-
-
-
-/* Types d'opérations binaires */
-typedef enum _ConvBinaryOperation
-{
- CBO_EOR, /* Ou exclusif (booléen) */
-
- CBO_COUNT
-
-} ConvBinaryOperation;
-
-
-/* Représentation d'une expression de conversion */
-typedef struct _conv_expr_t conv_expr_t;
-
-
-
-/* Référence une variable en tant qu'expression de conversion. */
-conv_expr_t *build_conv_expr_from_name(char *);
+#include <stdbool.h>
-/* Conserve une valeur en tant qu'expression de conversion. */
-conv_expr_t *build_conv_expr_from_number(unsigned long );
-
-/* Construit une base d'expression de conversion composée. */
-conv_expr_t *build_composed_conv_expr(char *, char *);
-
-/* Etend une base d'expression de conversion composée. */
-conv_expr_t *extend_composed_conv_expr(conv_expr_t *, char *);
-
-/* Traduit une opération unaire sur expression de conversion. */
-conv_expr_t *build_unary_conv_expr(conv_expr_t *, ConvUnaryOperation);
-
-/* Traduit une opération binaire sur expression de conversion. */
-conv_expr_t *build_binary_conv_expr(conv_expr_t *, conv_expr_t *, ConvBinaryOperation);
-
-
-
-
-
-
-
-
-/* ------------------------ LISTES D'ARGUMENTS DE CONVERSION ------------------------ */
-
-
-/* Liste d'expressions utilisées en arguments de conversion */
-typedef struct _conv_arg_list_t conv_arg_list_t;
-
-
-/* Crée une liste d'arguments de conversion. */
-conv_arg_list_t *build_conv_arg_list(conv_expr_t *);
-
-/* Libère la mémoire occupée par une liste d'expressions. */
-void delete_conv_arg_list(conv_arg_list_t *);
-
-/* Ajoute un élément à une liste d'arguments de conversion. */
-conv_arg_list_t *extend_conv_arg_list(conv_arg_list_t *, conv_expr_t *);
+#include "args.h"
+#include "bits.h"
+#include "pproc.h"
@@ -118,10 +42,10 @@ typedef struct _conv_func conv_func;
/* Définit une conversion à partir d'une simple expression. */
-conv_func *make_conv_from_expr(char *, conv_expr_t *);
+conv_func *make_conv_from_expr(char *, arg_expr_t *);
/* Définit une conversion à partir d'une function à appeler. */
-conv_func *make_conv_from_func(char *, char *, conv_arg_list_t *);
+conv_func *make_conv_from_func(char *, char *, arg_list_t *);
/* Libère de la mémoire une conversion enregistrée. */
void delete_conv_func(conv_func *);
@@ -129,6 +53,12 @@ void delete_conv_func(conv_func *);
/* Indique la variable de destination d'une conversion. */
const char *get_conv_dest_name(const conv_func *);
+/* Indique la nature d'une conversion : fonction ou expression ? */
+bool is_conv_func_expression(const conv_func *);
+
+/* Détermine la taille en bits du résultat d'une fonction. */
+bool compute_conv_func_size(const conv_func *, const coding_bits *, const conv_list *, unsigned int *);
+
/* Marque les champs utilisés par une fonction de conversion. */
bool mark_conv_func(conv_func *, const coding_bits *, const conv_list *);
@@ -143,6 +73,10 @@ bool define_conv_func(conv_func *, bool, bool, int, const char *, const coding_b
/* ---------------------------- ENSEMBLES DE CONVERSIONS ---------------------------- */
+/* Liste des fonctions de conversions présentes */
+typedef struct _conv_list conv_list;
+
+
/* Crée un nouvelle liste vierge de fonctions de conversion. */
conv_list *create_conv_list(void);
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/d2c_gram.y
index 12eff11..9e1e034 100644
--- a/tools/d2c/d2c_gram.y
+++ b/tools/d2c/d2c_gram.y
@@ -33,6 +33,7 @@ static void show_usage(const char *);
#include "coder.h"
#include "conv.h"
+#include "helpers.h"
struct action_tmp
{
@@ -95,13 +96,13 @@ struct action_tmp
register_hook_function(__hooks, t, f); \
})
-#define add_conditional_rule_to_coder(c, e, a, d) \
+#define add_conditional_rule_to_coder(c, e, a) \
({ \
encoding_spec *__spec; \
decoding_rules *__rules; \
__spec = get_current_encoding_spec(c); \
__rules = get_rules_in_encoding_spec(__spec); \
- register_conditional_rule(__rules, e, a, d); \
+ register_conditional_rule(__rules, e, a); \
})
}
@@ -115,15 +116,15 @@ struct action_tmp
int integer;
conv_func *subst; /* Fonction de conversion */
- conv_arg_list_t *conv_list; /* Liste d'arguments de conv. */
+ arg_list_t *args; /* Liste d'arguments */
- conv_expr_t *conv; /* Expression de conversion */
+ arg_expr_t *arg; /* Argument multi-usages */
ConvUnaryOperation un_op; /* Opération unaire */
ConvBinaryOperation bin_op; /* Opération bianire */
cond_expr *expr; /* Expression de déclenchement */
- struct action_tmp tmpa; /* Transfert temporaire */
+ rule_action raction; /* Action et éléments associés */
}
@@ -146,7 +147,7 @@ struct action_tmp
%token HOOKS
-%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE UNPREDICTABLE
+%token RULES IF EXPR_START EQUAL BINVAL IMMVAL EXPR_END AND THEN SEE CALL UNPREDICTABLE
%type <string> COPYRIGHT INS_NAME
@@ -160,17 +161,17 @@ struct action_tmp
%type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
-
%type <subst> substitution
-%type <conv_list> conv_arg_list
-%type <conv> conv_expr conv_arg_composed
-%type <un_op> conv_expr_un_op
-%type <bin_op> conv_expr_bin_op
-%type <string> conv_arg_field
+
+%type <args> arg_list
+%type <arg> arg_expr arg_composed
+%type <un_op> arg_expr_un_op
+%type <bin_op> arg_expr_bin_op
+%type <string> arg_field
%type <expr> rule_cond
%type <string> BINVAL IMMVAL
-%type <tmpa> action
+%type <raction> action
%%
@@ -231,28 +232,29 @@ conversions : CONV substitutions
substitutions : /* empty */
| substitutions substitution { register_conversion_in_coder(coder, $2); }
-substitution : NAME EQ conv_expr { $$ = make_conv_from_expr($1, $3); }
- | NAME EQ NAME OP conv_arg_list CP { $$ = make_conv_from_func($1, $3, $5); }
+substitution : NAME EQ arg_expr { $$ = make_conv_from_expr($1, $3); }
+ | NAME EQ NAME OP arg_list CP { $$ = make_conv_from_func($1, $3, $5); }
+
-conv_arg_list : conv_expr { $$ = build_conv_arg_list($1); }
- | conv_arg_list COMMA conv_expr { $$ = extend_conv_arg_list($1, $3); printf("extend\n"); }
+arg_list : arg_expr { $$ = build_arg_list($1); }
+ | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); }
-conv_expr : NAME { $$ = build_conv_expr_from_name($1); }
- | NUMBER { $$ = build_conv_expr_from_number($1); }
- | conv_arg_composed { $$ = $1; }
- | OP conv_expr CP { $$ = $2; }
- | conv_expr_un_op conv_expr { $$ = build_unary_conv_expr($2, $1); }
- | OP conv_expr conv_expr_bin_op conv_expr CP { $$ = build_binary_conv_expr($2, $4, $3); }
+arg_expr : NAME { $$ = build_arg_expr_from_name($1); }
+ | NUMBER { $$ = build_arg_expr_from_number($1); }
+ | arg_composed { $$ = $1; }
+ | OP arg_expr CP { $$ = $2; }
+ | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); }
+ | OP arg_expr arg_expr_bin_op arg_expr CP { $$ = build_binary_arg_expr($2, $4, $3); }
-conv_expr_un_op : NOT { $$ = CUO_NOT; }
+arg_expr_un_op : NOT { $$ = CUO_NOT; }
-conv_expr_bin_op : EOR { $$ = CBO_EOR; }
+arg_expr_bin_op : EOR { $$ = CBO_EOR; }
-conv_arg_composed : conv_arg_field COLON conv_arg_field { $$ = build_composed_conv_expr($1, $3); }
- | conv_arg_composed COLON conv_arg_field { $$ = extend_composed_conv_expr($1, $3); }
+arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); }
+ | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); }
-conv_arg_field : NAME { $$ = $1; printf(" composed::name '%s'\n", $1); }
- | BINVAL { $$ = $1; printf(" composed::bin '%s'\n", $1); }
+arg_field : NAME { $$ = $1; }
+ | BINVAL { $$ = $1; }
hooks : HOOKS hookings
@@ -268,16 +270,17 @@ rules : RULES rules_list
rules_list : /* empty */
| rules_list rule
-rule : IF EXPR_START rule_cond EXPR_END THEN action
- { add_conditional_rule_to_coder(coder, $3, $6.action, $6.details); }
+rule : IF EXPR_START rule_cond EXPR_END THEN action { add_conditional_rule_to_coder(coder, $3, &$6); }
+ | action { add_conditional_rule_to_coder(coder, NULL, &$1); }
rule_cond : NAME EQUAL BINVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
| NAME EQUAL IMMVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3); }
| EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END
{ $$ = build_composed_cond_expression($2, COT_AND, $6); }
-action : SEE INS_DETAILS { $$.action = CAT_SEE; $$.details = $2; }
- | UNPREDICTABLE { $$.action = CAT_UNPREDICTABLE; $$.details = NULL; }
+action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_callable($2, false); }
+ | UNPREDICTABLE { $$.type = CAT_UNPREDICTABLE; }
+ | CALL NAME OP arg_list CP { $$.type = CAT_CALL; $$.callee = $2; $$.args = $4; }
%%
diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l
index 8f54c8d..9689b59 100644
--- a/tools/d2c/d2c_tok.l
+++ b/tools/d2c/d2c_tok.l
@@ -19,7 +19,9 @@ void free_flex_memory(void) ;
%option noyywrap
%option nounput
%option noinput
-%option yylineno
+%option yylineno
+%option stack
+%option noyy_top_state
%x comments
@@ -33,9 +35,11 @@ void free_flex_memory(void) ;
%x conv_begin conv_content conv_arg conv_arg_binval
+%x arg arg_binval
+
%x hooks_begin hooks_content
-%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see
+%x rules_begin rules_content rules_cond rules_cond_binval rules_action rules_action_see rules_action_call
%%
@@ -127,6 +131,10 @@ void free_flex_memory(void) ;
}
<conv_content>"=" { return EQ; }
<conv_content>"(" { BEGIN(conv_arg); return OP; }
+
+
+
+
<conv_arg>[A-Za-z][A-Za-z0-9_]* {
if (strcmp(yytext, "NOT") == 0) return NOT;
else if (strcmp(yytext, "EOR") == 0) return EOR;
@@ -147,6 +155,33 @@ void free_flex_memory(void) ;
+
+
+
+
+
+
+<arg>[A-Za-z][A-Za-z0-9_]* {
+ if (strcmp(yytext, "NOT") == 0) return NOT;
+ else if (strcmp(yytext, "EOR") == 0) return EOR;
+ else
+ {
+ d2c_lval.string = strdup(yytext);
+ return NAME;
+ }
+ }
+<arg>[0-9][0-9]* { d2c_lval.integer = atoi(yytext); return NUMBER; }
+<arg>"'" { BEGIN(arg_binval); }
+<arg_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; }
+<arg_binval>"'" { BEGIN(arg); }
+<arg>"," { return COMMA; }
+<arg>":" { return COLON; }
+<arg>[ ]+ { }
+<arg>")" { yy_pop_state(); return CP; }
+
+
+
+
<encoding_content>"@hooks" { BEGIN(hooks_begin); return HOOKS; }
<hooks_begin>[ ]+ { }
<hooks_begin>"{" { BEGIN(hooks_content); }
@@ -165,6 +200,10 @@ void free_flex_memory(void) ;
<rules_content>[ \t\n]+ { }
<rules_content>"}" { BEGIN(encoding_content); }
+<rules_content>"see " { BEGIN(rules_action_see); return SEE; }
+<rules_content>"unpredictable" { return UNPREDICTABLE; }
+<rules_content>"call" { BEGIN(rules_action_call); return CALL; }
+
<rules_content>"if" { BEGIN(rules_cond); return IF; }
<rules_cond>[ ]+ { }
<rules_cond>"(" { return EXPR_START; }
@@ -179,10 +218,18 @@ void free_flex_memory(void) ;
<rules_cond>";" { BEGIN(rules_action); return THEN; }
<rules_action>[ ]+ { }
+
<rules_action>"see " { BEGIN(rules_action_see); return SEE; }
<rules_action_see>[^\n]* { d2c_lval.cstring = yytext; BEGIN(rules_content); return INS_DETAILS; }
+
<rules_action>"unpredictable" { BEGIN(rules_content); return UNPREDICTABLE; }
+<rules_action>"call" { BEGIN(rules_action_call); return CALL; }
+<rules_action_call>[\t ]+ { }
+<rules_action_call>[A-Za-z][A-Za-z0-9]* { d2c_lval.string = strdup(yytext); return NAME; }
+<rules_action_call>"(" { yy_push_state(arg); return OP; }
+<rules_action_call>[\n] { BEGIN(rules_content); }
+
%%
diff --git a/tools/d2c/qckcall.c b/tools/d2c/qckcall.c
new file mode 100644
index 0000000..ce9a0b2
--- /dev/null
+++ b/tools/d2c/qckcall.c
@@ -0,0 +1,110 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * qckcall.c - appel rapide et facilité à une fonction C de Chrysalide
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "qckcall.h"
+
+
+#include <malloc.h>
+#include <regex.h>
+#include <string.h>
+#include <sys/param.h>
+
+
+#include "helpers.h"
+
+
+
+/******************************************************************************
+* *
+* Paramètres : callee = fonction appelée à nomer. *
+* args = précise si la conversion est la dernière. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
+* *
+* Description : Réalise un appel à une fonction liée à une instruction. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool call_instr_func(const char *callee, const arg_list_t *args, int fd, const coding_bits *bits, const conv_list *list, const pre_processor *pp)
+{
+ bool result; /* Bilan à remonter */
+ regex_t preg; /* Expression régulière */
+ int ret; /* Bilan d'une manipulation */
+ regmatch_t pmatch[3]; /* Correspondances de chaînes */
+ size_t cmplen; /* Taille de comparaison */
+ char *cast; /* Macro de transtypage */
+
+ ret = regcomp(&preg, "(g_([a-z0-9]*)_instruction)", REG_EXTENDED);
+ if (ret != 0)
+ {
+ fprintf(stderr, "Internal error: bad regular expression.\n");
+ return false;
+ }
+
+ ret = regexec(&preg, callee, sizeof(pmatch) / sizeof(regmatch_t), pmatch, 0);
+ if (ret == REG_NOMATCH)
+ {
+ fprintf(stderr, "Internal error: bad function for dealing wih instruction: '%s'.\n", callee);
+ result = false;
+ goto cif_exit;
+ }
+
+ /**
+ * La variable de résultat est de type 'GArchInstruction',
+ * donc toute fonction différente de g_arch_instruction_*() attend un transtypage...
+ */
+
+ cmplen = MAX(strlen("arch"), pmatch[2].rm_eo - pmatch[2].rm_so);
+
+ if (strncmp("arch", &callee[pmatch[2].rm_so], cmplen) == 0)
+ dprintf(fd, "\t\tif (!%s(instr, ", callee);
+
+ else
+ {
+ cast = strndup(&callee[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so);
+
+ cast = make_string_upper(cast);
+
+ dprintf(fd, "\t\tif (!%s(%s(instr), ", callee, cast);
+
+ free(cast);
+
+ }
+
+ result = define_arg_list(args, fd, bits, list);
+
+ dprintf(fd, "))\n");
+
+ cif_exit:
+
+ regfree(&preg);
+
+ return result;
+
+}
diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h
new file mode 100644
index 0000000..59d4adc
--- /dev/null
+++ b/tools/d2c/qckcall.h
@@ -0,0 +1,44 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * qckcall.h - prototypes pour un appel rapide et facilité à une fonction C de Chrysalide
+ *
+ * Copyright (C) 2015 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * OpenIDA is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * OpenIDA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _TOOLS_QCKCALL_H
+#define _TOOLS_QCKCALL_H
+
+
+#include <stdbool.h>
+
+
+
+#include "args.h"
+#include "conv.h"
+#include "bits.h"
+#include "pproc.h"
+
+
+
+/* Réalise un appel à une fonction liée à une instruction. */
+bool call_instr_func(const char *, const arg_list_t *, int, const coding_bits *, const conv_list *, const pre_processor *);
+
+
+
+#endif /* _TOOLS_QCKCALL_H */
diff --git a/tools/d2c/rules.c b/tools/d2c/rules.c
index 73ec965..6f2e075 100644
--- a/tools/d2c/rules.c
+++ b/tools/d2c/rules.c
@@ -30,6 +30,7 @@
#include "helpers.h"
+#include "qckcall.h"
@@ -79,8 +80,7 @@ static bool write_cond_expr(const cond_expr *, int, const coding_bits *);
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. */
+ rule_action action; /* Conséquence d'une validation*/
} extra_rule;
@@ -320,12 +320,31 @@ decoding_rules *create_decoding_rules(void)
void delete_decoding_rules(decoding_rules *rules)
{
size_t i; /* Boucle de parcours */
+ extra_rule *rule; /* Règle à traiter */
for (i = 0; i < rules->extra_count; i++)
{
- delete_cond_expr(rules->extra[i].expr);
- if (rules->extra[i].details)
- free(rules->extra[i].details);
+ rule = &rules->extra[i];
+
+ if (rule->expr != NULL)
+ delete_cond_expr(rule->expr);
+
+ switch (rule->action.type)
+ {
+ case CAT_SEE:
+ free(rule->action.details);
+ break;
+
+ case CAT_UNPREDICTABLE:
+ break;
+
+ case CAT_CALL:
+ free(rule->action.callee);
+ delete_arg_list(rule->action.args);
+ break;
+
+ }
+
}
if (rules->extra != NULL)
@@ -341,7 +360,6 @@ void delete_decoding_rules(decoding_rules *rules)
* Paramètres : rules = ensemble de règles à compléter. *
* expr = représentation d'expression à conserver. *
* action = conséquence associée à la règle. *
-* details = éventuel complément d'informations. *
* *
* Description : Ajoute une règle complète à la définition d'un codage. *
* *
@@ -351,7 +369,7 @@ void delete_decoding_rules(decoding_rules *rules)
* *
******************************************************************************/
-void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActionType action, const char *details)
+void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rule_action *action)
{
extra_rule *rule; /* Nouvelle prise en compte */
@@ -360,8 +378,7 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
rule = &rules->extra[rules->extra_count - 1];
rule->expr = expr;
- rule->action = action;
- rule->details = (details != NULL ? make_callable(details, false) : NULL);
+ rule->action = *action;
}
@@ -369,10 +386,13 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
/******************************************************************************
* *
* Paramètres : rules = ensemble de règles à consulter. *
+* filter = filtre sur les règles à effectivement imprimer. *
* fd = descripteur d'un flux ouvert en écriture. *
* arch = architecture visée par l'opération. *
* subarch = sous-catégorie de cette même architecture. *
* bits = gestionnaire des bits d'encodage. *
+* list = liste de l'ensemble des fonctions de conversion. *
+* pp = pré-processeur pour les échanges de chaînes. *
* exit = exprime le besoin d'une voie de sortie. [OUT] *
* *
* Description : Traduit en code les éventuelles règles présentes. *
@@ -383,40 +403,39 @@ void register_conditional_rule(decoding_rules *rules, cond_expr *expr, CondActio
* *
******************************************************************************/
-bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const char *subarch, const coding_bits *bits, bool *exit)
+bool write_decoding_rules(decoding_rules *rules, CondActionType filter, int fd, const char *arch, const char *subarch, const coding_bits *bits, const conv_list *list, const pre_processor *pp, bool *exit)
{
bool result; /* Bilan à remonter */
const extra_rule *rule; /* Règle en cours d'écriture */
size_t i; /* Boucle de parcours */
+ const char *callable; /* Fonction à appeler */
result = true;
- *exit = false;
-
for (i = 0; i < rules->extra_count; i++)
{
rule = &rules->extra[i];
- dprintf(fd, "\t\tif ");
+ if (rule->action.type != filter)
+ continue;
- result = write_cond_expr(rule->expr, fd, bits);
- if (!result) break;
+ if (rule->expr != NULL)
+ {
+ dprintf(fd, "\t\tif ");
- dprintf(fd, "\n");
- dprintf(fd, "\t\t{\n");
+ result = write_cond_expr(rule->expr, fd, bits);
+ if (!result) break;
- switch (rule->action)
+ dprintf(fd, "\n");
+ dprintf(fd, "\t\t{\n");
+
+ }
+
+ switch (rule->action.type)
{
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 = %s_read_%sinstr_%s", arch, subarch, rule->details);
+ dprintf(fd, "\t\t\tinstr = %s_read_%sinstr_%s", arch, subarch, rule->action.details);
/* TODO : adapter les paramètres d'appel selon le 'coder' */
dprintf(fd, "(_raw);\n");
@@ -429,16 +448,35 @@ bool write_decoding_rules(decoding_rules *rules, int fd, const char *arch, const
case CAT_UNPREDICTABLE:
break;
+ case CAT_CALL:
+
+ callable = find_macro(pp, rule->action.callee);
+
+ if (callable == NULL)
+ callable = rule->action.callee;
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ result = call_instr_func(callable, rule->action.args, fd, bits, list, pp);
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ dprintf(fd, "\t\t\tgoto quick_exit;\n");
+
+ *exit = true;
+ break;
+
}
- dprintf(fd, "\t\t}\n");
+ if (rule->expr != NULL)
+ dprintf(fd, "\t\t}\n");
dprintf(fd, "\n");
}
- wcsr_exit:
-
return result;
}
diff --git a/tools/d2c/rules.h b/tools/d2c/rules.h
index af2cac5..6344828 100644
--- a/tools/d2c/rules.h
+++ b/tools/d2c/rules.h
@@ -25,7 +25,10 @@
#define _TOOLS_RULES_H
+#include "args.h"
#include "bits.h"
+#include "conv.h"
+#include "pproc.h"
@@ -67,10 +70,33 @@ cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
typedef enum _CondActionType
{
CAT_SEE, /* Renvoi vers une instruction */
- CAT_UNPREDICTABLE /* Cas de figure improbable */
+ CAT_UNPREDICTABLE, /* Cas de figure improbable */
+ CAT_CALL /* Appel à une fonction C */
} CondActionType;
+/* Définition d'une action de règle */
+typedef struct _rule_action
+{
+ CondActionType type; /* Conséquence d'une validation*/
+
+ union
+ {
+ /* CAT_SEE */
+ char *details; /* Eventuel complément d'info. */
+
+ /* CAT_CALL */
+ struct
+ {
+ char *callee; /* Fonction appelée */
+ arg_list_t *args; /* Arguments à fournir */
+
+ };
+
+ };
+
+} rule_action;
+
/* Règles de décodage supplémentaires */
typedef struct _decoding_rules decoding_rules;
@@ -82,10 +108,10 @@ decoding_rules *create_decoding_rules(void);
void delete_decoding_rules(decoding_rules *);
/* Ajoute une règle complète à la définition d'un codage. */
-void register_conditional_rule(decoding_rules *, cond_expr *, CondActionType, const char *);
+void register_conditional_rule(decoding_rules *, cond_expr *, const rule_action *);
/* Traduit en code les éventuelles règles présentes. */
-bool write_decoding_rules(decoding_rules *, int, const char *, const char *, const coding_bits *, bool *);
+bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *);
diff --git a/tools/d2c/spec.c b/tools/d2c/spec.c
index b56c6aa..9d4447d 100644
--- a/tools/d2c/spec.c
+++ b/tools/d2c/spec.c
@@ -304,7 +304,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
/* Inclusion des éventuelles règles */
- result &= write_decoding_rules(spec->rules, fd, arch, subarch, spec->bits, &exit);
+ exit = false;
+
+ result &= write_decoding_rules(spec->rules, CAT_SEE,
+ fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
+
+ result &= write_decoding_rules(spec->rules, CAT_UNPREDICTABLE,
+ fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
/* Création de l'instruction en elle-même */
@@ -314,10 +320,13 @@ bool write_encoding_spec_disass(const encoding_spec *spec, int fd, const char *a
dprintf(fd, "\n");
- /* Inscriptions des éventuelles fonctions à lier */
+ /* Inscriptions des éventuelles fonctions ou propriété à lier */
result &= write_hook_functions(spec->hooks, fd);
+ result &= write_decoding_rules(spec->rules, CAT_CALL,
+ fd, arch, subarch, spec->bits, spec->conversions, pp, &exit);
+
/* Création des opérandes */
result &= define_syntax_items(spec->syntax, fd, arch, spec->bits, spec->conversions, pp);