summaryrefslogtreecommitdiff
path: root/tools/d2c/rules
diff options
context:
space:
mode:
Diffstat (limited to 'tools/d2c/rules')
-rw-r--r--tools/d2c/rules/Makefile.am31
-rw-r--r--tools/d2c/rules/decl.h37
-rw-r--r--tools/d2c/rules/grammar.y162
-rw-r--r--tools/d2c/rules/manager.c531
-rw-r--r--tools/d2c/rules/manager.h120
-rw-r--r--tools/d2c/rules/tokens.l57
6 files changed, 938 insertions, 0 deletions
diff --git a/tools/d2c/rules/Makefile.am b/tools/d2c/rules/Makefile.am
new file mode 100644
index 0000000..c2d9d96
--- /dev/null
+++ b/tools/d2c/rules/Makefile.am
@@ -0,0 +1,31 @@
+
+BUILT_SOURCES = grammar.h
+
+
+# On évite d'utiliser les variables personnalisées de type *_la_[YL]FLAGS
+# afin de conserver des noms de fichiers simples, ie sans le nom de la
+# bibliothèque de sortie en préfixe.
+
+AM_YFLAGS = -v -d -p rules_
+
+AM_LFLAGS = -P rules_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=rules_lval -Dyyget_lineno=rules_get_lineno \
+ -Dyy_scan_string=rules__scan_string \
+ -Dyy_delete_buffer=rules__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2crules.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2crules_la_SOURCES = \
+ decl.h \
+ manager.h manager.c \
+ tokens.l \
+ grammar.y
+
+
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
diff --git a/tools/d2c/rules/decl.h b/tools/d2c/rules/decl.h
new file mode 100644
index 0000000..f7d7960
--- /dev/null
+++ b/tools/d2c/rules/decl.h
@@ -0,0 +1,37 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * decl.h - déclarations de prototypes utiles
+ *
+ * Copyright (C) 2016 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_D2C_RULES_DECL_H
+#define _TOOLS_D2C_RULES_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données relatives à un bloc règles. */
+bool load_rules_from_raw_block(decoding_rules *, const char *);
+
+
+
+#endif /* _TOOLS_D2C_RULES_DECL_H */
diff --git a/tools/d2c/rules/grammar.y b/tools/d2c/rules/grammar.y
new file mode 100644
index 0000000..effd4b3
--- /dev/null
+++ b/tools/d2c/rules/grammar.y
@@ -0,0 +1,162 @@
+
+%{
+
+#include "tokens.h"
+#include "../helpers.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(decoding_rules *, char *);
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+#include "../args/decl.h"
+
+}
+
+
+%union {
+
+ char *string; /* Chaîne de caractères #1 */
+ const char *cstring; /* Chaîne de caractères #2 */
+
+ cond_expr *expr; /* Expression de déclenchement */
+ rule_action raction; /* Action et éléments associés */
+}
+
+
+%define api.pure full
+
+%parse-param { decoding_rules *rules }
+
+%code provides {
+
+#define YY_DECL \
+ int rules_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token IF EXPR_START EXPR_END THEN
+
+%token SEE CALL CHK_CALL UNPREDICTABLE
+
+%token NAME
+
+%token EQUAL BINVAL HEXVAL
+
+%token AND AND_LOG
+
+%token RAW_LINE
+
+
+%type <string> NAME
+
+%type <cstring> RAW_LINE
+
+%type <expr> rule_cond
+%type <string> BINVAL HEXVAL
+%type <raction> action
+
+
+%%
+
+
+rules_list : /* empty */
+ | rules_list rule
+
+rule : IF EXPR_START rule_cond EXPR_END THEN action { register_conditional_rule(rules, $3, &$6); }
+ | action { register_conditional_rule(rules, NULL, &$1); }
+
+rule_cond : NAME EQUAL BINVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, true); }
+ | NAME EQUAL HEXVAL { $$ = build_simple_cond_expression($1, CCT_EQUAL, $3, false); }
+ | NAME AND_LOG BINVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, true); }
+ | NAME AND_LOG HEXVAL { $$ = build_simple_cond_expression($1, CCT_AND, $3, false); }
+ | EXPR_START rule_cond EXPR_END AND EXPR_START rule_cond EXPR_END
+ { $$ = build_composed_cond_expression($2, COT_AND, $6); }
+
+action : SEE RAW_LINE { $$.type = CAT_SEE; $$.details = make_callable($2, false); }
+ | UNPREDICTABLE { $$.type = CAT_UNPREDICTABLE; }
+ | CALL RAW_LINE {
+ right_op_t rop;
+ bool status;
+
+ status = load_call_from_raw_line(&rop, $2);
+ if (!status) YYABORT;
+
+ $$.type = CAT_CALL; $$.callee = rop.func; $$.args = rop.args;
+
+ }
+ | CHK_CALL RAW_LINE {
+ right_op_t rop;
+ bool status;
+
+ status = load_call_from_raw_line(&rop, $2);
+ if (!status) YYABORT;
+
+ $$.type = CAT_CHECKED_CALL; $$.callee = rop.func; $$.args = rop.args;
+
+ }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = structure impliquée dans le processus. *
+* msg = message d'erreur. *
+* *
+* Description : Affiche un message d'erreur suite à l'analyse en échec. *
+* *
+* Retour : 0 *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int yyerror(decoding_rules *rules, char *msg)
+{
+ printf("yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives à un bloc règles. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_rules_from_raw_block(decoding_rules *rules, const char *raw)
+{
+ bool result; /* Bilan à faire remonter */
+ YY_BUFFER_STATE state; /* Support d'analyse */
+ int status; /* Bilan de l'analyse */
+
+ state = yy_scan_string(raw);
+
+ status = yyparse(rules);
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
diff --git a/tools/d2c/rules/manager.c b/tools/d2c/rules/manager.c
new file mode 100644
index 0000000..f30559e
--- /dev/null
+++ b/tools/d2c/rules/manager.c
@@ -0,0 +1,531 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour les variations de décodage selon certaines conditions
+ *
+ * Copyright (C) 2014 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 "manager.h"
+
+
+#include <malloc.h>
+#include <stdbool.h>
+#include <string.h>
+
+
+#include "../helpers.h"
+#include "../qckcall.h"
+
+
+
+/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */
+
+
+/* Expression d'une condition */
+struct _cond_expr
+{
+ bool is_simple; /* Sélection de champ */
+
+ union
+ {
+ struct
+ {
+ char *variable; /* Variable manipulée */
+ CondCompType comp; /* Type de comparaison */
+ char *value; /* Valeur binaire comparée */
+
+ bool is_binary; /* Binaire ou hexadécimal */
+
+ } simple;
+
+ struct
+ {
+ cond_expr *a; /* Première sous-expression */
+ CondOpType operator; /* Relation entre expressions */
+ cond_expr *b; /* Seconde sous-expression */
+
+ } composed;
+
+ };
+
+};
+
+
+/* Libère de la mémoire une expression conditionnelle. */
+static void delete_cond_expr(cond_expr *);
+
+/* Traduit en code une expression de condition. */
+static bool write_cond_expr(const cond_expr *, int, const coding_bits *);
+
+
+
+/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */
+
+
+/* Règle particulière */
+typedef struct _extra_rule
+{
+ cond_expr *expr; /* Expression de déclenchement */
+ rule_action action; /* Conséquence d'une validation*/
+
+} extra_rule;
+
+/* Règles de décodage supplémentaires */
+struct _decoding_rules
+{
+ extra_rule *extra; /* Règles conditionnelles */
+ size_t extra_count; /* Nombre de ces règles */
+
+};
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* CONDITIONS DE DECLENCHEMENTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : variable = désignation de la variable à manipuler. *
+* comp = type de comparaison à utiliser. *
+* value = valeur binaire à comparer. *
+* is_binary = indique la nature de la valeur transmise. *
+* *
+* Description : Crée une expression conditionnelle simple. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cond_expr *build_simple_cond_expression(char *variable, CondCompType comp, char *value, bool is_binary)
+{
+ cond_expr *result; /* Structure à retourner */
+
+ result = (cond_expr *)calloc(1, sizeof(cond_expr));
+
+ result->is_simple = true;
+
+ result->simple.variable = make_string_lower(variable);
+ result->simple.comp = comp;
+ result->simple.value = value;
+
+ result->simple.is_binary = is_binary;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : a = première expression à intégrer. *
+* operator = type de comparaison à utiliser. *
+* b = second expression à intégrer. *
+* *
+* Description : Crée une expression conditionnelle composée. *
+* *
+* Retour : Structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+cond_expr *build_composed_cond_expression(cond_expr *a, CondOpType operator, cond_expr *b)
+{
+ cond_expr *result; /* Structure à retourner */
+
+ result = (cond_expr *)calloc(1, sizeof(cond_expr));
+
+ result->is_simple = false;
+
+ result->composed.a = a;
+ result->composed.operator = operator;
+ result->composed.b = b;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = représentation d'expression à traiter. *
+* *
+* Description : Libère de la mémoire une expression conditionnelle. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void delete_cond_expr(cond_expr *expr)
+{
+ if (expr->is_simple)
+ {
+ free(expr->simple.variable);
+ free(expr->simple.value);
+ }
+ else
+ {
+ delete_cond_expr(expr->composed.a);
+ delete_cond_expr(expr->composed.b);
+ }
+
+ free(expr);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : expr = expression simple ou composée à transposer. *
+* fd = descripteur d'un flux ouvert en écriture. *
+* bits = gestionnaire des bits d'encodage. *
+* *
+* Description : Traduit en code une expression de condition. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool write_cond_expr(const cond_expr *expr, int fd, const coding_bits *bits)
+{
+ bool result; /* Bilan à renvoyer */
+ const raw_bitfield *bf; /* Champ de bits de définition */
+ unsigned int provided; /* Nombre de bits fournis */
+
+ result = true;
+
+ dprintf(fd, "(");
+
+ if (expr->is_simple)
+ {
+ bf = find_named_field_in_bits(bits, expr->simple.variable);
+ if (bf == NULL)
+ {
+ fprintf(stderr, "Error: no bitfield defined the requested variable '%s'.\n", expr->simple.variable);
+ result = false;
+ goto wce_exit;
+ }
+
+ if (expr->simple.is_binary)
+ provided = strlen(expr->simple.value);
+ else
+ provided = 4 * strlen(expr->simple.value);
+
+ if (get_raw_bitfield_length(bf) != provided)
+ {
+ fprintf(stderr, "Error: variable '%s' and provided value sizes do not match (%u vs %u).\n",
+ expr->simple.variable, get_raw_bitfield_length(bf), provided);
+ result = false;
+ goto wce_exit;
+ }
+
+ dprintf(fd, "raw_%s", expr->simple.variable);
+
+ switch (expr->simple.comp)
+ {
+ case CCT_EQUAL:
+ dprintf(fd, " == ");
+ break;
+ case CCT_DIFF:
+ dprintf(fd, " != ");
+ break;
+ case CCT_AND:
+ dprintf(fd, " & ");
+ break;
+ }
+
+ if (expr->simple.is_binary)
+ dprintf(fd, "b%s", expr->simple.value);
+ else
+ dprintf(fd, "0x%s", expr->simple.value);
+
+ }
+ else
+ {
+ result = write_cond_expr(expr->composed.a, fd, bits);
+ if (!result) goto wce_exit;
+
+ switch (expr->composed.operator)
+ {
+ case COT_AND:
+ dprintf(fd, " && ");
+ break;
+ case COT_OR:
+ dprintf(fd, " || ");
+ break;
+ }
+
+ result = write_cond_expr(expr->composed.b, fd, bits);
+ if (!result) goto wce_exit;
+
+ }
+
+ dprintf(fd, ")");
+
+ wce_exit:
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* REGLES ET ACTIONS CONSEQUENTES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau rassemblement de règles de décodage. *
+* *
+* Retour : Nouvelle structure prête à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+decoding_rules *create_decoding_rules(void)
+{
+ decoding_rules *result; /* Définition vierge à renvoyer*/
+
+ result = (decoding_rules *)calloc(1, sizeof(decoding_rules));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles de décodage à supprimer. *
+* *
+* Description : Supprime de la mémoire un ensemble de règles supplémentaires.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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++)
+ {
+ 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:
+ case CAT_CHECKED_CALL:
+ free(rule->action.callee);
+ delete_arg_list(rule->action.args);
+ break;
+
+ }
+
+ }
+
+ if (rules->extra != NULL)
+ free(rules->extra);
+
+ free(rules);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : rules = ensemble de règles à compléter. *
+* expr = représentation d'expression à conserver. *
+* action = conséquence associée à la règle. *
+* *
+* Description : Ajoute une règle complète à la définition d'un codage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void register_conditional_rule(decoding_rules *rules, cond_expr *expr, const rule_action *action)
+{
+ extra_rule *rule; /* Nouvelle prise en compte */
+
+ rules->extra = (extra_rule *)realloc(rules->extra, ++rules->extra_count * sizeof(extra_rule));
+
+ rule = &rules->extra[rules->extra_count - 1];
+
+ rule->expr = expr;
+ rule->action = *action;
+
+}
+
+
+/******************************************************************************
+* *
+* 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. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+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 */
+ size_t i; /* Boucle de parcours */
+ const extra_rule *rule; /* Règle en cours d'écriture */
+ bool multi_lines; /* Nécessite des accolades */
+ const char *callable; /* Fonction à appeler */
+
+ result = true;
+
+ for (i = 0; i < rules->extra_count; i++)
+ {
+ rule = &rules->extra[i];
+
+ if (rule->action.type != filter)
+ continue;
+
+ switch (rule->action.type)
+ {
+ case CAT_CALL:
+ multi_lines = false;
+ break;
+
+ default:
+ multi_lines = true;
+ break;
+
+ }
+
+ if (rule->expr != NULL)
+ {
+ dprintf(fd, "\t\tif ");
+
+ result = write_cond_expr(rule->expr, fd, bits);
+ if (!result) break;
+
+ dprintf(fd, "\n");
+
+ if (multi_lines)
+ dprintf(fd, "\t\t{\n");
+
+ }
+
+ switch (rule->action.type)
+ {
+ case CAT_SEE:
+
+#if 0
+ 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");
+
+ dprintf(fd, "\t\t\tgoto quick_exit;\n");
+
+ *exit = true;
+#endif
+ break;
+
+ 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);
+
+ break;
+
+ case CAT_CHECKED_CALL:
+
+ callable = find_macro(pp, rule->action.callee);
+
+ if (callable == NULL)
+ callable = rule->action.callee;
+
+ if (rule->expr != NULL)
+ dprintf(fd, "\t");
+
+ result = checked_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;
+
+ }
+
+ if (rule->expr != NULL && multi_lines)
+ dprintf(fd, "\t\t}\n");
+
+ dprintf(fd, "\n");
+
+ }
+
+ return result;
+
+}
diff --git a/tools/d2c/rules/manager.h b/tools/d2c/rules/manager.h
new file mode 100644
index 0000000..f8ff2d6
--- /dev/null
+++ b/tools/d2c/rules/manager.h
@@ -0,0 +1,120 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manager.h - prototypes pour les variations de décodage selon certaines conditions
+ *
+ * Copyright (C) 2014 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_D2C_RULES_MANAGER_H
+#define _TOOLS_D2C_RULES_MANAGER_H
+
+
+#include "../pproc.h"
+#include "../args/manager.h"
+#include "../bits/manager.h"
+#include "../conv/manager.h"
+
+
+
+/* -------------------------- CONDITIONS DE DECLENCHEMENTS -------------------------- */
+
+
+/* Types de comparaison */
+typedef enum _CondCompType
+{
+ CCT_EQUAL, /* Egalité '==' */
+ CCT_DIFF, /* Différence '!=' */
+ CCT_AND /* Et logique '&' */
+
+} CondCompType;
+
+/* Types de combinaison d'expressions */
+typedef enum _CondOpType
+{
+ COT_AND, /* Combinaison ET ('&&') */
+ COT_OR /* Combinaison OU ('||') */
+
+} CondOpType;
+
+/* Expression d'une condition */
+typedef struct _cond_expr cond_expr;
+
+
+/* Crée une expression conditionnelle simple. */
+cond_expr *build_simple_cond_expression(char *, CondCompType, char *, bool);
+
+/* Crée une expression conditionnelle composée. */
+cond_expr *build_composed_cond_expression(cond_expr *, CondOpType, cond_expr *);
+
+
+
+/* ------------------------- REGLES ET ACTIONS CONSEQUENTES ------------------------- */
+
+
+/* Conséquence en cas de condition remplie */
+typedef enum _CondActionType
+{
+ CAT_SEE, /* Renvoi vers une instruction */
+ CAT_UNPREDICTABLE, /* Cas de figure improbable */
+ CAT_CALL, /* Appel à une fonction C */
+ CAT_CHECKED_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;
+
+
+/* Crée un nouveau rassemblement de règles de décodage. */
+decoding_rules *create_decoding_rules(void);
+
+/* Supprime de la mémoire un ensemble de règles supplémentaires. */
+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 *, const rule_action *);
+
+/* Traduit en code les éventuelles règles présentes. */
+bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, const char *, const coding_bits *, const conv_list *, const pre_processor *, bool *);
+
+
+
+#endif /* _TOOLS_D2C_RULES_MANAGER_H */
diff --git a/tools/d2c/rules/tokens.l b/tools/d2c/rules/tokens.l
new file mode 100644
index 0000000..36d6c4a
--- /dev/null
+++ b/tools/d2c/rules/tokens.l
@@ -0,0 +1,57 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+%x cond
+%x cond_binval
+%x cond_hexval
+%x action
+%x raw_line
+
+
+%%
+
+
+\/\/[^\n]+ { printf("SKIP '%s'\n", yytext); }
+
+"if" { yy_push_state(cond); return IF; }
+<cond>[ ]+ { }
+<cond>"(" { return EXPR_START; }
+<cond>[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; }
+<cond>"==" { return EQUAL; }
+<cond>"'" { yy_push_state(cond_binval); }
+<cond_binval>[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; }
+<cond_binval>"'" { yy_pop_state(); }
+<cond>"0x" { yy_push_state(cond_hexval); }
+<cond_hexval>[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; }
+<cond>")" { return EXPR_END; }
+<cond>"&&" { return AND; }
+<cond>"&" { return AND_LOG; }
+
+<cond>";" { yy_pop_state(); return THEN; }
+
+[ ] { }
+
+"see " { yy_push_state(raw_line); return SEE; }
+
+"unpredictable" { return UNPREDICTABLE; }
+
+"call" { yy_push_state(raw_line); return CALL; }
+"chk_call" { yy_push_state(raw_line); return CHK_CALL; }
+
+<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; }
+<raw_line>"\n" { yy_pop_state(); }
+
+
+%%