summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2016-01-28 23:32:25 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2016-01-28 23:32:25 (GMT)
commit16e0fd9d89ef433848678dfc8dd20426844a2868 (patch)
tree79075ae02c133cea21ffb555b1086aae833b3aac /tools
parent66c99d59d6a6d533de0bb65488de8243213bcdea (diff)
Cleaned, rewritten and improved the whole code of the compiler.
Diffstat (limited to 'tools')
-rw-r--r--tools/d2c/Makefile.am49
-rw-r--r--tools/d2c/args/Makefile.am31
-rw-r--r--tools/d2c/args/decl.h54
-rw-r--r--tools/d2c/args/grammar.y191
-rw-r--r--tools/d2c/args/manager.c (renamed from tools/d2c/args.c)8
-rw-r--r--tools/d2c/args/manager.h (renamed from tools/d2c/args.h)12
-rw-r--r--tools/d2c/args/tokens.l67
-rw-r--r--tools/d2c/bits/Makefile.am31
-rw-r--r--tools/d2c/bits/decl.h37
-rw-r--r--tools/d2c/bits/grammar.y117
-rw-r--r--tools/d2c/bits/manager.c (renamed from tools/d2c/bits.c)8
-rw-r--r--tools/d2c/bits/manager.h (renamed from tools/d2c/bits.h)8
-rw-r--r--tools/d2c/bits/tokens.l33
-rw-r--r--tools/d2c/coder.c23
-rw-r--r--tools/d2c/coder.h9
-rw-r--r--tools/d2c/conv/Makefile.am31
-rw-r--r--tools/d2c/conv/decl.h37
-rw-r--r--tools/d2c/conv/grammar.y130
-rw-r--r--tools/d2c/conv/manager.c (renamed from tools/d2c/conv.c)8
-rw-r--r--tools/d2c/conv/manager.h (renamed from tools/d2c/conv.h)14
-rw-r--r--tools/d2c/conv/tokens.l32
-rw-r--r--tools/d2c/d2c.mk2
-rw-r--r--tools/d2c/d2c_tok.l235
-rw-r--r--tools/d2c/grammar.y (renamed from tools/d2c/d2c_gram.y)313
-rw-r--r--tools/d2c/helpers.h6
-rw-r--r--tools/d2c/hooks/Makefile.am31
-rw-r--r--tools/d2c/hooks/decl.h37
-rw-r--r--tools/d2c/hooks/grammar.y109
-rw-r--r--tools/d2c/hooks/manager.c (renamed from tools/d2c/hooks.c)6
-rw-r--r--tools/d2c/hooks/manager.h (renamed from tools/d2c/hooks.h)8
-rw-r--r--tools/d2c/hooks/tokens.l26
-rw-r--r--tools/d2c/manual.h65
-rw-r--r--tools/d2c/pproc.h6
-rw-r--r--tools/d2c/qckcall.h13
-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.c (renamed from tools/d2c/rules.c)8
-rw-r--r--tools/d2c/rules/manager.h (renamed from tools/d2c/rules.h)16
-rw-r--r--tools/d2c/rules/tokens.l57
-rw-r--r--tools/d2c/spec.h16
-rw-r--r--tools/d2c/syntax/Makefile.am31
-rw-r--r--tools/d2c/syntax/decl.h37
-rw-r--r--tools/d2c/syntax/grammar.y109
-rw-r--r--tools/d2c/syntax/manager.c (renamed from tools/d2c/syntax.c)6
-rw-r--r--tools/d2c/syntax/manager.h (renamed from tools/d2c/syntax.h)14
-rw-r--r--tools/d2c/syntax/tokens.l39
-rw-r--r--tools/d2c/tokens.l132
48 files changed, 1971 insertions, 511 deletions
diff --git a/tools/d2c/Makefile.am b/tools/d2c/Makefile.am
index 63ca5fe..e89384f 100644
--- a/tools/d2c/Makefile.am
+++ b/tools/d2c/Makefile.am
@@ -1,35 +1,46 @@
-BUILT_SOURCES = d2c-d2c_gram.h
+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 d2c_
+
+AM_LFLAGS = -P d2c_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=d2c_lval -Dyyget_lineno=d2c_get_lineno \
+ -Dyy_scan_bytes=d2c__scan_bytes \
+ -Dyy_delete_buffer=d2c__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
-AM_YFLAGS = -d
bin_PROGRAMS = d2c
+.NOTPARALLEL: $(bin_PROGRAMS)
d2c_SOURCES = \
- args.h args.c \
- bits.h bits.c \
coder.h coder.c \
- conv.h conv.c \
- d2c_tok.l \
- d2c_gram.y \
+ tokens.l \
+ grammar.y \
helpers.h helpers.c \
- hooks.h hooks.c \
+ manual.h \
pproc.h pproc.c \
qckcall.h qckcall.c \
- rules.h rules.c \
- spec.h spec.c \
- syntax.h syntax.c
+ spec.h spec.c
-d2c_YFLAGS = -v -d -p d2c_ -o y.tab.c
+d2c_LDADD = \
+ bits/libd2cbits.la \
+ conv/libd2cconv.la \
+ hooks/libd2chooks.la \
+ rules/libd2crules.la \
+ syntax/libd2csyntax.la \
+ args/libd2cargs.la
-d2c_LFLAGS = -P d2c_ --header-file=d2c_tok.h -o lex.yy.c
-
-AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
-
-AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+# Automake fait les choses à moitié
+CLEANFILES = grammar.h grammar.c grammar.output tokens.c tokens.h
-# Automake fait les choses à moitié
-CLEANFILES = d2c_gram.h d2c_gram.c d2c-d2c_tok.c
+SUBDIRS = args bits conv hooks rules syntax
diff --git a/tools/d2c/args/Makefile.am b/tools/d2c/args/Makefile.am
new file mode 100644
index 0000000..2a4cb4d
--- /dev/null
+++ b/tools/d2c/args/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 args_
+
+AM_LFLAGS = -P args_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=args_lval -Dyyget_lineno=args_get_lineno \
+ -Dyy_scan_string=args__scan_string \
+ -Dyy_delete_buffer=args__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2cargs.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2cargs_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/args/decl.h b/tools/d2c/args/decl.h
new file mode 100644
index 0000000..8d64eaa
--- /dev/null
+++ b/tools/d2c/args/decl.h
@@ -0,0 +1,54 @@
+
+/* 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_ARGS_DECL_H
+#define _TOOLS_D2C_ARGS_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Encapsulation de réponses multiples */
+typedef struct _right_op_t
+{
+ char *func; /* Eventuelle fonction d'appel */
+
+ union
+ {
+ arg_list_t *args; /* Liste d'arguments */
+ arg_expr_t *expr; /* Argument multi-usages */
+ };
+
+} right_op_t;
+
+
+/* Interprête des données relatives un opérande de droite. */
+bool load_args_from_raw_line(right_op_t *, const char *);
+
+/* Interprête des données relatives à un appel avec arguments. */
+bool load_call_from_raw_line(right_op_t *, const char *);
+
+
+
+#endif /* _TOOLS_D2C_ARGS_DECL_H */
diff --git a/tools/d2c/args/grammar.y b/tools/d2c/args/grammar.y
new file mode 100644
index 0000000..6477c47
--- /dev/null
+++ b/tools/d2c/args/grammar.y
@@ -0,0 +1,191 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(right_op_t *, unsigned int *, char *);
+
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+
+}
+
+
+%union {
+
+ right_op_t operand; /* Construction finale */
+
+ char *string; /* Chaîne de caractères */
+ int integer; /* Valeur numérique entière */
+
+ arg_list_t *args; /* Liste d'arguments */
+ arg_expr_t *arg; /* Argument multi-usages */
+ ConvUnaryOperation un_op; /* Opération unaire */
+ ConvBinaryOperation bin_op; /* Opération bianire */
+
+}
+
+
+%define api.pure full
+
+%parse-param { right_op_t *operand } { unsigned int *init_token }
+%lex-param { unsigned int *init_token }
+
+%code provides {
+
+#define YY_DECL \
+ int args_lex(YYSTYPE *yylvalp, unsigned int *init_token)
+
+YY_DECL;
+
+}
+
+
+%token FORCE_EXPR FORCE_CALL ALLOW_ALL
+%token NAME
+%token NUMBER BINVAL HEXVAL
+%token COMMA COLON OP CP
+%token NOT AND_LOG EOR
+
+
+%type <string> NAME
+%type <integer> NUMBER
+%type <string> BINVAL HEXVAL
+
+%type <operand> call
+%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
+
+
+%%
+
+
+right_op : FORCE_EXPR arg_expr { operand->func = NULL; operand->expr = $2; }
+ | FORCE_CALL call { *operand = $2; }
+ | arg_expr { operand->func = NULL; operand->expr = $1; }
+ | call { *operand = $1; }
+
+call : NAME OP arg_list CP { $$.func = $1; $$.args = $3; }
+
+arg_list : arg_expr { $$ = build_arg_list($1); }
+ | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); }
+
+arg_expr : NAME { $$ = build_arg_expr_from_name($1); }
+ | NUMBER { $$ = build_arg_expr_from_number($1); }
+ | BINVAL { $$ = build_arg_expr_from_binval($1); }
+ | HEXVAL { $$ = build_arg_expr_from_hexval($1); }
+ | arg_composed { $$ = $1; }
+ | OP arg_expr CP { $$ = $2; }
+ | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); }
+ | arg_expr arg_expr_bin_op arg_expr { $$ = build_binary_arg_expr($1, $3, $2); }
+
+arg_expr_un_op : NOT { $$ = CUO_NOT; }
+
+arg_expr_bin_op : AND_LOG { $$ = CBO_AND; }
+ | EOR { $$ = CBO_EOR; }
+
+arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); }
+ | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); }
+
+arg_field : NAME { $$ = $1; }
+ | BINVAL { $$ = $1; }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = structure impliquée dans le processus. *
+* init_token = éventuel jeton d'initialisation ou NULL. *
+* msg = message d'erreur. *
+* *
+* Description : Affiche un message d'erreur suite à l'analyse en échec. *
+* *
+* Retour : 0 *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int yyerror(right_op_t *operand, unsigned int *init_token, char *msg)
+{
+ printf("args yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives un opérande de droite. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_args_from_raw_line(right_op_t *operand, 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(operand, (unsigned int []) { ALLOW_ALL });
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : operand = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives à un appel avec arguments. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_call_from_raw_line(right_op_t *operand, 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(operand, (unsigned int []) { FORCE_CALL });
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
diff --git a/tools/d2c/args.c b/tools/d2c/args/manager.c
index f933160..ce300e6 100644
--- a/tools/d2c/args.c
+++ b/tools/d2c/args/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * args.c - gestion des arguments dans leur ensemble
+ * manager.c - gestion des arguments dans leur ensemble
*
* Copyright (C) 2015 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "args.h"
+#include "manager.h"
#include <assert.h>
@@ -29,8 +29,8 @@
#include <string.h>
-#include "conv.h"
-#include "helpers.h"
+#include "../helpers.h"
+#include "../conv/manager.h"
diff --git a/tools/d2c/args.h b/tools/d2c/args/manager.h
index b9f210b..85fc0a8 100644
--- a/tools/d2c/args.h
+++ b/tools/d2c/args/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * args.h - prototypes pour la gestion des arguments dans leur ensemble
+ * manager.h - prototypes pour la gestion des arguments dans leur ensemble
*
* Copyright (C) 2015 Cyrille Bagard
*
@@ -21,12 +21,12 @@
*/
-#ifndef _TOOLS_ARGS_H
-#define _TOOLS_ARGS_H
+#ifndef _TOOLS_D2C_ARGS_MANAGER_H
+#define _TOOLS_D2C_ARGS_MANAGER_H
-#include "bits.h"
-#include "pproc.h"
+#include "../pproc.h"
+#include "../bits/manager.h"
/* Liste des fonctions de conversions présentes */
@@ -135,4 +135,4 @@ bool define_arg_list(const arg_list_t *, int, const coding_bits *, const conv_li
-#endif /* _TOOLS_ARGS_H */
+#endif /* _TOOLS_D2C_ARGS_MANAGER_H */
diff --git a/tools/d2c/args/tokens.l b/tools/d2c/args/tokens.l
new file mode 100644
index 0000000..4b1a2a1
--- /dev/null
+++ b/tools/d2c/args/tokens.l
@@ -0,0 +1,67 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+%x binval
+%x hexval
+
+
+%%
+
+
+%{
+
+ /* Choix d'un des démarrages multiples */
+ if (*init_token != ALLOW_ALL)
+ {
+ unsigned int first;
+ first = *init_token;
+ *init_token = ALLOW_ALL;
+ return first;
+ }
+
+%}
+
+
+[A-Za-z_][A-Za-z0-9_]* {
+ if (strcmp(yytext, "NOT") == 0) return NOT;
+ else if (strcmp(yytext, "AND") == 0) return AND_LOG;
+ else if (strcmp(yytext, "EOR") == 0) return EOR;
+ else
+ {
+ yylvalp->string = strdup(yytext);
+ return NAME;
+ }
+ }
+
+[0-9][0-9]* { yylvalp->integer = atoi(yytext); return NUMBER; }
+
+"'" { yy_push_state(binval); }
+<binval>[01][01]* { yylvalp->string = strdup(yytext); return BINVAL; }
+<binval>"'" { yy_pop_state(); }
+
+"0x" { yy_push_state(hexval); }
+<hexval>[0-9a-f][0-9a-f]* { yylvalp->string = strdup(yytext); yy_pop_state(); return HEXVAL; }
+
+"," { return COMMA; }
+":" { return COLON; }
+"&" { return AND_LOG; }
+
+"(" { yy_push_state(INITIAL); return OP; }
+")" { yy_pop_state(); return CP; }
+
+[ ]+ { }
+
+
+%%
diff --git a/tools/d2c/bits/Makefile.am b/tools/d2c/bits/Makefile.am
new file mode 100644
index 0000000..415e2a6
--- /dev/null
+++ b/tools/d2c/bits/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 bits_
+
+AM_LFLAGS = -P bits_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=bits_lval -Dyyget_lineno=bits_get_lineno \
+ -Dyy_scan_string=bits__scan_string \
+ -Dyy_delete_buffer=bits__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2cbits.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2cbits_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/bits/decl.h b/tools/d2c/bits/decl.h
new file mode 100644
index 0000000..2e9d223
--- /dev/null
+++ b/tools/d2c/bits/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_BITS_DECL_H
+#define _TOOLS_D2C_BITS_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données relatives à un champ de bits. */
+bool load_bits_from_raw_line(coding_bits *, unsigned int, const char *);
+
+
+
+#endif /* _TOOLS_D2C_BITS_DECL_H */
diff --git a/tools/d2c/bits/grammar.y b/tools/d2c/bits/grammar.y
new file mode 100644
index 0000000..a5d0de7
--- /dev/null
+++ b/tools/d2c/bits/grammar.y
@@ -0,0 +1,117 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(coding_bits *, char *);
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+
+}
+
+
+%union {
+
+ char *string; /* Chaîne de caractères */
+ int integer; /* Valeur numérique entière */
+
+}
+
+
+%define api.pure full
+
+%parse-param { coding_bits *bits }
+
+%code provides {
+
+#define YY_DECL \
+ int bits_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token NAME SIZE BIT
+
+%type <string> NAME
+%type <integer> SIZE BIT
+
+
+%%
+
+
+bitfield : /* empty */
+ | NAME SIZE bitfield { register_named_field_in_bits(bits, $1, $2); }
+ | BIT bitfield { register_bit_in_bits(bits, $1); }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = 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(coding_bits *bits, char *msg)
+{
+ printf("bits yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : bits = structure à constituer à partir de données lues. *
+* expected = nombre de bits définis à attendre. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives à un champ de bits. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_bits_from_raw_line(coding_bits *bits, unsigned int expected, 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(bits);
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ if (result && count_coded_bits(bits) != expected)
+ {
+ fprintf(stderr, "Unexpected word size: %u vs %u\n", count_coded_bits(bits), expected);
+ result = false;
+ }
+
+ return result;
+
+}
diff --git a/tools/d2c/bits.c b/tools/d2c/bits/manager.c
index 4169acf..db6392d 100644
--- a/tools/d2c/bits.c
+++ b/tools/d2c/bits/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * bits.c - compréhension et manipulation des champs de bits
+ * manager.c - compréhension et manipulation des champs de bits
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "bits.h"
+#include "manager.h"
#include <assert.h>
@@ -31,9 +31,7 @@
#include <string.h>
-#include "helpers.h"
-
-
+#include "../helpers.h"
diff --git a/tools/d2c/bits.h b/tools/d2c/bits/manager.h
index aa4b7aa..3269d69 100644
--- a/tools/d2c/bits.h
+++ b/tools/d2c/bits/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * bits.h - prototypes pour la compréhension et la manipulation des champs de bits
+ * manager.h - prototypes pour la compréhension et la manipulation des champs de bits
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _TOOLS_BITS_H
-#define _TOOLS_BITS_H
+#ifndef _TOOLS_D2C_BITS_MANAGER_H
+#define _TOOLS_D2C_BITS_MANAGER_H
#include <stdbool.h>
@@ -84,4 +84,4 @@ bool define_used_bits_fields(const coding_bits *, int);
-#endif /* _TOOLS_BITS_H */
+#endif /* _TOOLS_D2C_BITS_MANAGER_H */
diff --git a/tools/d2c/bits/tokens.l b/tools/d2c/bits/tokens.l
new file mode 100644
index 0000000..99fb96d
--- /dev/null
+++ b/tools/d2c/bits/tokens.l
@@ -0,0 +1,33 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+%x bsize
+
+
+%%
+
+
+" " { }
+
+[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; }
+
+"(" { yy_push_state(bsize); }
+<bsize>[0-9]+ { yylvalp->integer = atoi(yytext); return SIZE; }
+<bsize>")" { yy_pop_state(); }
+
+[01] { yylvalp->integer = atoi(yytext); return BIT; }
+
+
+%%
diff --git a/tools/d2c/coder.c b/tools/d2c/coder.c
index c709bcf..83910aa 100644
--- a/tools/d2c/coder.c
+++ b/tools/d2c/coder.c
@@ -181,8 +181,27 @@ bool do_basic_checks_with_coder(const rented_coder *coder)
/******************************************************************************
* *
-* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
-* outdir = fichier de définitions à venir lire. *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* *
+* Description : Indique le fichier de définition considéré en entrée. *
+* *
+* Retour : Fichier de définition à interpréter. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *get_coder_input_file(const rented_coder *coder)
+{
+ return coder->input;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : coder = gestion par la machine en remplacement de l'humain. *
+* input = fichier de définitions à venir lire. *
* *
* Description : Spécifie le fichier de définition à prendre en entrée. *
* *
diff --git a/tools/d2c/coder.h b/tools/d2c/coder.h
index aadb2d4..d9f0f0e 100644
--- a/tools/d2c/coder.h
+++ b/tools/d2c/coder.h
@@ -21,8 +21,8 @@
*/
-#ifndef _ARCH_ARM_V7_OPDEFS_CODER_H
-#define _ARCH_ARM_V7_OPDEFS_CODER_H
+#ifndef _TOOLS_D2C_CODER_H
+#define _TOOLS_D2C_CODER_H
#include <stdbool.h>
@@ -50,6 +50,9 @@ void delete_coder(rented_coder *);
/* Détermine si les propriétés de base d'un codeur sont là. */
bool do_basic_checks_with_coder(const rented_coder *);
+/* Indique le fichier de définition considéré en entrée. */
+const char *get_coder_input_file(const rented_coder *);
+
/* Spécifie le fichier de définition à prendre en entrée. */
void set_coder_input_file(rented_coder *, const char *);
@@ -125,4 +128,4 @@ bool dump_all_routines_using_coder(const rented_coder *);
-#endif /* _ARCH_ARM_V7_OPDEFS_CODER_H */
+#endif /* _TOOLS_D2C_CODER_H */
diff --git a/tools/d2c/conv/Makefile.am b/tools/d2c/conv/Makefile.am
new file mode 100644
index 0000000..7744bc0
--- /dev/null
+++ b/tools/d2c/conv/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 conv_
+
+AM_LFLAGS = -P conv_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=conv_lval -Dyyget_lineno=conv_get_lineno \
+ -Dyy_scan_string=conv__scan_string \
+ -Dyy_delete_buffer=conv__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2cconv.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2cconv_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/conv/decl.h b/tools/d2c/conv/decl.h
new file mode 100644
index 0000000..e1388fe
--- /dev/null
+++ b/tools/d2c/conv/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_CONV_DECL_H
+#define _TOOLS_D2C_CONV_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données relatives à un bloc de conversions. */
+bool load_convs_from_raw_block(conv_list *, const char *);
+
+
+
+#endif /* _TOOLS_D2C_CONV_DECL_H */
diff --git a/tools/d2c/conv/grammar.y b/tools/d2c/conv/grammar.y
new file mode 100644
index 0000000..71fcc47
--- /dev/null
+++ b/tools/d2c/conv/grammar.y
@@ -0,0 +1,130 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(conv_list *, 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 */
+
+ conv_func *subst; /* Fonction de conversion */
+
+}
+
+
+%define api.pure full
+
+%parse-param { conv_list *list }
+
+%code provides {
+
+#define YY_DECL \
+ int conv_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token NAME
+%token EQ
+%token RAW_LINE
+
+%type <string> NAME
+%type <cstring> RAW_LINE
+
+%type <subst> substitution
+
+
+%%
+
+
+substitutions : /* empty */
+ | substitutions substitution { register_conversion(list, $2); }
+
+substitution : NAME EQ RAW_LINE {
+ right_op_t rop;
+ bool status;
+
+ status = load_args_from_raw_line(&rop, $3);
+ if (!status) YYABORT;
+
+ if (rop.func == NULL)
+ $$ = make_conv_from_expr($1, rop.expr);
+ else
+ $$ = make_conv_from_func($1, rop.func, rop.args);
+
+ }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : list = 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(conv_list *list, char *msg)
+{
+ printf("yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives à un bloc de conversions. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_convs_from_raw_block(conv_list *list, 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(list);
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
diff --git a/tools/d2c/conv.c b/tools/d2c/conv/manager.c
index 3fae6df..c04a49e 100644
--- a/tools/d2c/conv.c
+++ b/tools/d2c/conv/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * conv.c - substitutions de valeurs depuis un contenu binaire
+ * manager.c - substitutions de valeurs depuis un contenu binaire
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "conv.h"
+#include "manager.h"
#include <assert.h>
@@ -31,8 +31,8 @@
#include <string.h>
-#include "helpers.h"
-#include "qckcall.h"
+#include "../helpers.h"
+#include "../qckcall.h"
diff --git a/tools/d2c/conv.h b/tools/d2c/conv/manager.h
index 85c7578..abd6c6f 100644
--- a/tools/d2c/conv.h
+++ b/tools/d2c/conv/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * conv.h - prototypes pour les substitutions de valeurs depuis un contenu binaire
+ * manager.h - prototypes pour les substitutions de valeurs depuis un contenu binaire
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,16 +21,16 @@
*/
-#ifndef _TOOLS_CONV_H
-#define _TOOLS_CONV_H
+#ifndef _TOOLS_D2C_CONV_MANAGER_H
+#define _TOOLS_D2C_CONV_MANAGER_H
#include <stdbool.h>
-#include "args.h"
-#include "bits.h"
-#include "pproc.h"
+#include "../pproc.h"
+#include "../args/manager.h"
+#include "../bits/manager.h"
@@ -91,4 +91,4 @@ conv_func *find_named_conv_in_list(const conv_list *, const char *);
-#endif /* _TOOLS_CONV_H */
+#endif /* _TOOLS_D2C_CONV_MANAGER_H */
diff --git a/tools/d2c/conv/tokens.l b/tools/d2c/conv/tokens.l
new file mode 100644
index 0000000..ef6b958
--- /dev/null
+++ b/tools/d2c/conv/tokens.l
@@ -0,0 +1,32 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+%x raw_line
+
+
+%%
+
+
+[ \t\n]+ { }
+
+[A-Za-z_][A-Za-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; }
+
+"=" { yy_push_state(raw_line); return EQ; }
+
+<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; }
+<raw_line>"\n" { yy_pop_state(); }
+
+
+%%
diff --git a/tools/d2c/d2c.mk b/tools/d2c/d2c.mk
index 36bb38e..b0b7b92 100644
--- a/tools/d2c/d2c.mk
+++ b/tools/d2c/d2c.mk
@@ -19,7 +19,7 @@ fix_verbose_0 = echo " FIX " `basename $$f`;
SUFFIXES = .g
.d.g:
- $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS) < $<
+ $(d2c_verbose)$(D2C_BIN) -i $< -d $(D2C_OUTDIR) -a $(D2C_ARCH) -H $(D2C_HEADER) $(D2C_ENCODINGS) $(D2C_MACROS)
@touch $@
# Merci http://www.commandlinefu.com/commands/view/10276/grep-tab-t
diff --git a/tools/d2c/d2c_tok.l b/tools/d2c/d2c_tok.l
deleted file mode 100644
index 300508d..0000000
--- a/tools/d2c/d2c_tok.l
+++ /dev/null
@@ -1,235 +0,0 @@
-
-%{
-
-typedef struct _rented_coder rented_coder;
-
-
-#include "d2c-d2c_gram.h"
-
-#include <ctype.h>
-#include <string.h>
-
-
-/* Tente de libérer autant de mémoire que possible... */
-void free_flex_memory(void) ;
-
-
-%}
-
-%option noyywrap
-%option nounput
-%option noinput
-%option yylineno
-%option stack
-%option noyy_top_state
-
-
-%x comments
-
-%x ins_name try_details ins_details
-%x encoding encoding_type encoding_content
-
-%x encoding_bits encoding_bits_size
-
-%x syntax syntax_name syntax_int syntax_ext
-
-%x conv_begin conv_content
-
-%x arg arg_binval arg_hexval
-
-%x hooks_begin hooks_content
-
-%x rules_begin rules_content rules_cond rules_cond_binval rules_cond_hexval rules_action rules_action_see rules_action_call
-
-
-%%
-
-
-[ \t\n]+ { }
-
-"/*" { BEGIN(comments); }
-<comments>"*/" { BEGIN(INITIAL); }
-<comments>[^*\n] { }
-<comments>"Copyright"[^\n]* { d2c_lval.string = strdup(yytext); return COPYRIGHT; }
-<comments>"*" { }
-<comments>"\n" { }
-
-
-"@title" { BEGIN(ins_name); return TITLE; }
-
-<ins_name>[ ][A-Za-z-]+ { d2c_lval.string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
-<try_details>[ ,/] { BEGIN(ins_details); }
-<try_details>[\n] { BEGIN(INITIAL); }
-
-<ins_details>[^\n]* { d2c_lval.cstring = yytext; return INS_DETAILS; }
-<ins_details>[\n] { BEGIN(INITIAL); }
-
-
-
-"@encoding" { BEGIN(encoding); return ENCODING; }
-
-<encoding>[ ] { }
-<encoding>"(" { BEGIN(encoding_type); }
-
-<encoding_type>[A-Za-z] { d2c_lval.string = strdup(yytext); return TYPE; }
-<encoding_type>[0-9]+ { d2c_lval.integer = atoi(yytext); return NUMBER; }
-<encoding_type>")" { BEGIN(encoding); }
-
-<encoding>"{" { BEGIN(encoding_content); }
-<encoding_content>[ \t\n]+ { }
-<encoding_content>"}" { BEGIN(INITIAL); }
-
-
-
-<encoding_content>"@half" { BEGIN(encoding_bits); return HALF; }
-<encoding_content>"@word" { BEGIN(encoding_bits); return WORD; }
-
-<encoding_bits>" " { }
-<encoding_bits>"\n" { BEGIN(encoding_content); }
-<encoding_bits>[A-Za-z_][A-Za-z0-9__]* { d2c_lval.string = strdup(yytext); return NAME; }
-
-<encoding_bits>"(" { BEGIN(encoding_bits_size); }
-<encoding_bits_size>[0-9]+ { d2c_lval.integer = atoi(yytext); return SIZE; }
-<encoding_bits_size>")" { BEGIN(encoding_bits); }
-
-<encoding_bits>[01] { d2c_lval.integer = atoi(yytext); return BIT; }
-
-
-
-<encoding_content>"@syntax" { BEGIN(syntax); return SYNTAX; }
-
-<syntax>[ ]+ { }
-<syntax>"\n" { BEGIN(encoding_content); }
-
-<syntax>[\"] { BEGIN(syntax_name); }
-<syntax_name>[^ \n\"]+ { d2c_lval.string = strdup(yytext); return OPERAND_NAME; }
-<syntax_name>[\"] { BEGIN(syntax); }
-
-<syntax>"{" { BEGIN(syntax_int); }
-<syntax_int>[^ \n}]+ { d2c_lval.string = strdup(yytext); return OPERAND_INTERNAL; }
-<syntax_int>"}" { BEGIN(syntax); }
-
-<syntax>"<" { BEGIN(syntax_ext); }
-<syntax_ext>[^ \n>]+ { d2c_lval.string = strdup(yytext); return OPERAND_VISIBLE; }
-<syntax_ext>">" { BEGIN(syntax); }
-
-
-
-<encoding_content>"@conv" { BEGIN(conv_begin); return CONV; }
-<conv_begin>[ ]+ { }
-<conv_begin>"{" { BEGIN(conv_content); }
-<conv_content>"}" { BEGIN(encoding_content); }
-
-<conv_content>[ \t\n]+ { }
-<conv_content>[A-Za-z_][A-Za-z0-9_]* {
- if (strcmp(yytext, "NOT") == 0) return NOT;
- else
- {
- d2c_lval.string = strdup(yytext);
- return NAME;
- }
- }
-<conv_content>"=" { return EQ; }
-<conv_content>"(" { yy_push_state(arg); return OP; }
-
-
-
-
-<arg>[A-Za-z_][A-Za-z0-9_]* {
- if (strcmp(yytext, "NOT") == 0) return NOT;
- else if (strcmp(yytext, "AND") == 0) return AND_LOG;
- 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>"0x" { BEGIN(arg_hexval); }
-<arg_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(arg); return HEXVAL; }
-<arg>"," { return COMMA; }
-<arg>":" { return COLON; }
-<arg>"&" { return AND_LOG; }
-<arg>[ ]+ { }
-<arg>"(" { yy_push_state(arg); return OP; }
-<arg>")" { yy_pop_state(); return CP; }
-
-
-
-<encoding_content>"@hooks" { BEGIN(hooks_begin); return HOOKS; }
-<hooks_begin>[ ]+ { }
-<hooks_begin>"{" { BEGIN(hooks_content); }
-<hooks_content>"}" { BEGIN(encoding_content); }
-
-<hooks_content>[ \t\n]+ { }
-<hooks_content>[a-z_][a-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; }
-<hooks_content>"=" { return EQ; }
-
-
-
-<encoding_content>"@rules" { BEGIN(rules_begin); return RULES; }
-<rules_content>\/\/[^\n]+ { printf("SKIP '%s'\n", yytext); }
-<rules_begin>[ ]+ { }
-<rules_begin>"{" { BEGIN(rules_content); }
-<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>"chk_call" { BEGIN(rules_action_call); return CHK_CALL; }
-
-<rules_content>"if" { BEGIN(rules_cond); return IF; }
-<rules_cond>[ ]+ { }
-<rules_cond>"(" { return EXPR_START; }
-<rules_cond>[A-Za-z_][A-Za-z0-9_]* { d2c_lval.string = strdup(yytext); return NAME; }
-<rules_cond>"==" { return EQUAL; }
-<rules_cond>"'" { BEGIN(rules_cond_binval); }
-<rules_cond_binval>[01][01]* { d2c_lval.string = strdup(yytext); return BINVAL; }
-<rules_cond_binval>"'" { BEGIN(rules_cond); }
-<rules_cond>"0x" { BEGIN(rules_cond_hexval); }
-<rules_cond_hexval>[0-9a-f][0-9a-f]* { d2c_lval.string = strdup(yytext); BEGIN(rules_cond); return HEXVAL; }
-<rules_cond>")" { return EXPR_END; }
-<rules_cond>"&&" { return AND; }
-<rules_cond>"&" { return AND_LOG; }
-
-<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>"chk_call" { BEGIN(rules_action_call); return CHK_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); }
-
-
-%%
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Tente de libérer autant de mémoire que possible... *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void free_flex_memory(void)
-{
- yy_delete_buffer(YY_CURRENT_BUFFER);
-
-}
diff --git a/tools/d2c/d2c_gram.y b/tools/d2c/grammar.y
index 9827b05..986edd7 100644
--- a/tools/d2c/d2c_gram.y
+++ b/tools/d2c/grammar.y
@@ -2,107 +2,92 @@
%{
#include <getopt.h>
-#include <stdbool.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
-
-#include "coder.h"
-#include "d2c_tok.h"
-
-
-extern int yylex();
-
-extern void free_flex_memory(void);
+#include "tokens.h"
/* Affiche un message d'erreur suite à l'analyse en échec. */
-static int d2c_error(rented_coder *, char *);
+static int d2c_error(rented_coder *, char *, char *);
/* Affiche des indications sur l'utilisation du programme. */
static void show_usage(const char *);
+/* Prépare le traitement d'un contenu en l'affichant en mémoire. */
+static void *map_input_data(const char *, size_t *);
%}
%code requires {
-/* Pour la définition des expressions conditionnelles... */
#include "coder.h"
-
-#include "conv.h"
#include "helpers.h"
+#include "args/decl.h"
+#include "bits/decl.h"
+#include "conv/decl.h"
+#include "hooks/decl.h"
+#include "rules/decl.h"
+#include "syntax/decl.h"
-struct action_tmp
-{
- CondActionType action;
- const char *details;
-};
-
-#define register_named_field_in_coder(c, n, l) \
+#define handle_coder_bits(c, e, r) \
({ \
encoding_spec *__spec; \
coding_bits *__bits; \
+ bool __status; \
__spec = get_current_encoding_spec(c); \
__bits = get_bits_in_encoding_spec(__spec); \
- register_named_field_in_bits(__bits, n, l); \
+ __status = load_bits_from_raw_line(__bits, e, r); \
+ if (!__status) YYABORT; \
})
-#define register_bit_in_coder(c, v) \
- ({ \
- encoding_spec *__spec; \
- coding_bits *__bits; \
- __spec = get_current_encoding_spec(c); \
- __bits = get_bits_in_encoding_spec(__spec); \
- register_bit_in_bits(__bits, v); \
- })
-
-#define count_coder_bits(c) \
- ({ \
- encoding_spec *__spec; \
- coding_bits *__bits; \
- __spec = get_current_encoding_spec(c); \
- __bits = get_bits_in_encoding_spec(__spec); \
- count_coded_bits(__bits); \
- })
-
-#define register_syntax_item_in_coder(c, n, i) \
+#define handle_coder_syntax(c, r) \
({ \
encoding_spec *__spec; \
asm_syntax *__syntax; \
+ bool __status; \
__spec = get_current_encoding_spec(c); \
__syntax = get_syntax_in_encoding_spec(__spec); \
- register_syntax_item(__syntax, n, i); \
+ __status = load_syntax_from_raw_line(__syntax, r); \
+ if (!__status) YYABORT; \
})
-#define register_conversion_in_coder(c, f) \
+#define handle_coder_conversions(c, r) \
({ \
encoding_spec *__spec; \
conv_list *__list; \
+ bool __status; \
__spec = get_current_encoding_spec(c); \
__list = get_conversions_in_encoding_spec(__spec); \
- register_conversion(__list, f); \
+ __status = load_convs_from_raw_block(__list, r); \
+ if (!__status) YYABORT; \
})
-#define register_hook_in_coder(c, t, f) \
+#define handle_coder_hooks(c, r) \
({ \
encoding_spec *__spec; \
instr_hooks *__hooks;; \
+ bool __status; \
__spec = get_current_encoding_spec(c); \
__hooks = get_hooks_in_encoding_spec(__spec); \
- register_hook_function(__hooks, t, f); \
+ __status = load_hooks_from_raw_line(__hooks, r); \
+ if (!__status) YYABORT; \
})
-#define add_conditional_rule_to_coder(c, e, a) \
+#define handle_coder_rules(c, r) \
({ \
encoding_spec *__spec; \
decoding_rules *__rules; \
+ bool __status; \
__spec = get_current_encoding_spec(c); \
__rules = get_rules_in_encoding_spec(__spec); \
- register_conditional_rule(__rules, e, a); \
+ __status = load_rules_from_raw_block(__rules, r); \
+ if (!__status) YYABORT; \
})
}
@@ -112,23 +97,29 @@ struct action_tmp
char *string; /* Chaîne de caractères #1 */
const char *cstring; /* Chaîne de caractères #2 */
+ int integer; /* Valeur entière */
- int integer;
+}
- conv_func *subst; /* Fonction de conversion */
- arg_list_t *args; /* Liste d'arguments */
- arg_expr_t *arg; /* Argument multi-usages */
- ConvUnaryOperation un_op; /* Opération unaire */
- ConvBinaryOperation bin_op; /* Opération bianire */
+/**
+ * Cf.
+ * http://stackoverflow.com/questions/34418381/how-to-reference-lex-or-parse-parameters-in-flex-rules/34420950
+ */
+%define api.pure full
- cond_expr *expr; /* Expression de déclenchement */
- rule_action raction; /* Action et éléments associés */
+%parse-param { rented_coder *coder } { char *temp }
+%lex-param { char *temp }
-}
+%code provides {
-%parse-param { rented_coder *coder }
+#define YY_DECL \
+ int d2c_lex(YYSTYPE *yylvalp, char *temp)
+
+YY_DECL;
+
+}
%token COPYRIGHT
@@ -139,15 +130,13 @@ struct action_tmp
%token TYPE NUMBER
%token ENC_START ENC_END
-%token WORD HALF NAME SIZE BIT
-
-%token SYNTAX OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
-
-%token CONV EQ OP COMMA CP NOT AND_LOG EOR COLON
-
+%token WORD HALF
+%token SYNTAX
+%token CONV
%token HOOKS
+%token RULES
-%token RULES IF EXPR_START EQUAL BINVAL HEXVAL EXPR_END AND THEN SEE CALL CHK_CALL UNPREDICTABLE
+%token RAW_LINE RAW_BLOCK
%type <string> COPYRIGHT INS_NAME
@@ -156,22 +145,7 @@ struct action_tmp
%type <string> TYPE
%type <integer> NUMBER
-%type <string> NAME
-%type <integer> SIZE BIT
-
-%type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
-
-%type <subst> substitution
-
-%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 HEXVAL
-%type <raction> action
+%type <cstring> RAW_LINE RAW_BLOCK
%%
@@ -183,8 +157,6 @@ name : COPYRIGHT TITLE INS_NAME { save_notes_for_coder(coder, $1, $3
| COPYRIGHT TITLE INS_NAME INS_DETAILS { save_notes_for_coder(coder, $1, $3, $4); }
-
-
encodings : /* empty */
| encoding encodings
@@ -199,94 +171,16 @@ content : /* empty */
| rules content
-bitfield : HALF bits {
- if (count_coder_bits(coder) != 16)
- {
- fprintf(stderr, "Unexpected word size: %u vs 16\n", count_coder_bits(coder));
- YYABORT;
- }
- }
- | WORD bits {
- if (count_coder_bits(coder) != 32)
- {
- fprintf(stderr, "Unexpected word size: %u vs 32\n", count_coder_bits(coder));
- YYABORT;
- }
- }
-
-bits : /* empty */
- | NAME SIZE bits { register_named_field_in_coder(coder, $1, $2); }
- | BIT bits { register_bit_in_coder(coder, $1); }
-
-
-syntax : SYNTAX operands
-
-operands : /* empty */
- | operands OPERAND_NAME { register_syntax_item_in_coder(coder, $2, SIT_KEYWORD); }
- | operands OPERAND_INTERNAL { register_syntax_item_in_coder(coder, $2, SIT_INT_OPERAND); }
- | operands OPERAND_VISIBLE { register_syntax_item_in_coder(coder, $2, SIT_EXT_OPERAND); }
-
-
-conversions : CONV substitutions
-
-substitutions : /* empty */
- | substitutions substitution { register_conversion_in_coder(coder, $2); }
-
-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); }
-
-
-arg_list : arg_expr { $$ = build_arg_list($1); }
- | arg_list COMMA arg_expr { $$ = extend_arg_list($1, $3); }
-
-arg_expr : NAME { $$ = build_arg_expr_from_name($1); }
- | NUMBER { $$ = build_arg_expr_from_number($1); }
- | BINVAL { $$ = build_arg_expr_from_binval($1); }
- | HEXVAL { $$ = build_arg_expr_from_hexval($1); }
- | arg_composed { $$ = $1; }
- | OP arg_expr CP { $$ = $2; }
- | arg_expr_un_op arg_expr { $$ = build_unary_arg_expr($2, $1); }
- | arg_expr arg_expr_bin_op arg_expr { $$ = build_binary_arg_expr($1, $3, $2); }
-
-arg_expr_un_op : NOT { $$ = CUO_NOT; }
-
-arg_expr_bin_op : AND_LOG { $$ = CBO_AND; }
- | EOR { $$ = CBO_EOR; }
+bitfield : HALF RAW_LINE { handle_coder_bits(coder, 16, $2); }
+ | WORD RAW_LINE { handle_coder_bits(coder, 32, $2); }
-arg_composed : arg_field COLON arg_field { $$ = build_composed_arg_expr($1, $3); }
- | arg_composed COLON arg_field { $$ = extend_composed_arg_expr($1, $3); }
+syntax : SYNTAX RAW_LINE { handle_coder_syntax(coder, $2); }
-arg_field : NAME { $$ = $1; }
- | BINVAL { $$ = $1; }
+conversions : CONV RAW_BLOCK { handle_coder_conversions(coder, $2); }
+hooks : HOOKS RAW_BLOCK { handle_coder_hooks(coder, $2); }
-hooks : HOOKS hookings
-
-hookings : /* empty */
- | hookings hooking
-
-hooking : NAME EQ NAME { register_hook_in_coder(coder, $1, $3); }
-
-
-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 { add_conditional_rule_to_coder(coder, 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 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; }
- | CHK_CALL NAME OP arg_list CP { $$.type = CAT_CHECKED_CALL; $$.callee = $2; $$.args = $4; }
+rules : RULES RAW_BLOCK { handle_coder_rules(coder, $2); }
%%
@@ -295,6 +189,7 @@ action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_cal
/******************************************************************************
* *
* Paramètres : coder = codeur impliqué dans le processus. *
+* temp = zone de travail à destination des lectures manuelles.*
* msg = message d'erreur. *
* *
* Description : Affiche un message d'erreur suite à l'analyse en échec. *
@@ -305,7 +200,7 @@ action : SEE INS_DETAILS { $$.type = CAT_SEE; $$.details = make_cal
* *
******************************************************************************/
-static int d2c_error(rented_coder *coder, char *msg)
+static int d2c_error(rented_coder *coder, char *temp, char *msg)
{
printf("yyerror line %d: %s\n", d2c_get_lineno(), msg);
@@ -352,6 +247,63 @@ static void show_usage(const char *argv0)
/******************************************************************************
* *
+* Paramètres : filename = chemin du fichier à charger en mémoire. *
+* length = taille de l'espace mémoie à mettre en place. [OUT]*
+* *
+* Description : Prépare le traitement d'un contenu en l'affichant en mémoire.*
+* *
+* Retour : Adresse valide ou MAP_FAILED en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void *map_input_data(const char *filename, size_t *length)
+{
+ void *result; /* Espace mémoire à retourner */
+ int fd; /* Descripteur du fichier */
+ struct stat info; /* Informations sur le fichier */
+ int ret; /* Bilan d'un appel */
+
+ result = NULL;
+
+ fd = open(filename, O_RDONLY);
+ if (fd == -1)
+ {
+ perror("open");
+ goto mid_exit;
+ }
+
+ ret = fstat(fd, &info);
+ if (ret == -1)
+ {
+ perror("fstat");
+ goto mid_exit_with_fd;
+ }
+
+ *length = info.st_size;
+
+ result = mmap(NULL, *length, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (result == MAP_FAILED)
+ {
+ perror("mmap");
+ goto mid_exit_with_fd;
+ }
+
+ mid_exit_with_fd:
+
+ close(fd);
+
+ mid_exit:
+
+ return result;
+
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : argc = nombre d'arguments dans la ligne de commande. *
* argv = arguments de la ligne de commande. *
* *
@@ -372,6 +324,10 @@ int main(int argc, char **argv)
bool has_error; /* Erreur dans la ligne de cmd.*/
int ret; /* Bilan d'une lecture d'arg. */
char *sep; /* Caratère '=' en coupure */
+ size_t length; /* Nombre d'octets à traiter */
+ char *content; /* Contenu brut à analyser */
+ char *temp; /* Zone de travail temporaire */
+ YY_BUFFER_STATE state; /* Contexte d'analyse */
static struct option long_options[] = {
@@ -459,11 +415,26 @@ int main(int argc, char **argv)
goto exit;
}
- result = yyparse(coder);
+ content = map_input_data(get_coder_input_file(coder), &length);
+ if (content == MAP_FAILED)
+ {
+ result = EXIT_FAILURE;
+ goto exit;
+ }
- exit:
+ temp = (char *)calloc(length, sizeof(char));
- free_flex_memory();
+ state = d2c__scan_bytes(content, length);
+
+ result = yyparse(coder, temp);
+
+ yy_delete_buffer(state);
+
+ free(temp);
+
+ munmap(content, length);
+
+ exit:
delete_coder(coder);
diff --git a/tools/d2c/helpers.h b/tools/d2c/helpers.h
index 8c39a85..1df821c 100644
--- a/tools/d2c/helpers.h
+++ b/tools/d2c/helpers.h
@@ -21,8 +21,8 @@
*/
-#ifndef _TOOLS_HELPERS_H
-#define _TOOLS_HELPERS_H
+#ifndef _TOOLS_D2C_HELPERS_H
+#define _TOOLS_D2C_HELPERS_H
#include <ctype.h>
@@ -44,4 +44,4 @@ char *make_callable(const char *raw, bool);
-#endif /* _TOOLS_HELPERS_H */
+#endif /* _TOOLS_D2C_HELPERS_H */
diff --git a/tools/d2c/hooks/Makefile.am b/tools/d2c/hooks/Makefile.am
new file mode 100644
index 0000000..1eb00a8
--- /dev/null
+++ b/tools/d2c/hooks/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 hooks_
+
+AM_LFLAGS = -P hooks_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=hooks_lval -Dyyget_lineno=hooks_get_lineno \
+ -Dyy_scan_string=hooks__scan_string \
+ -Dyy_delete_buffer=hooks__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2chooks.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2chooks_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/hooks/decl.h b/tools/d2c/hooks/decl.h
new file mode 100644
index 0000000..7db5640
--- /dev/null
+++ b/tools/d2c/hooks/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_HOOKS_DECL_H
+#define _TOOLS_D2C_HOOKS_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données relatives à un champ de bits. */
+bool load_hooks_from_raw_line(instr_hooks *, const char *);
+
+
+
+#endif /* _TOOLS_D2C_HOOKS_DECL_H */
diff --git a/tools/d2c/hooks/grammar.y b/tools/d2c/hooks/grammar.y
new file mode 100644
index 0000000..43e7ba0
--- /dev/null
+++ b/tools/d2c/hooks/grammar.y
@@ -0,0 +1,109 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(instr_hooks *, char *);
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+
+}
+
+
+%union {
+
+ char *string; /* Chaîne de caractères */
+
+}
+
+
+%define api.pure full
+
+%parse-param { instr_hooks *hooks }
+
+%code provides {
+
+#define YY_DECL \
+ int hooks_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token NAME EQ
+
+%type <string> NAME
+
+
+%%
+
+
+hookings : /* empty */
+ | hookings hooking
+
+hooking : NAME EQ NAME { register_hook_function(hooks, $1, $3); }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : hooks = 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(instr_hooks *hooks, char *msg)
+{
+ printf("hooks yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : hooks = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données relatives à un champ de bits. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_hooks_from_raw_line(instr_hooks *hooks, 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(hooks);
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
diff --git a/tools/d2c/hooks.c b/tools/d2c/hooks/manager.c
index a110664..8e7ae77 100644
--- a/tools/d2c/hooks.c
+++ b/tools/d2c/hooks/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * syntax.c - prise en compte d'une syntaxe du langage d'assemblage
+ * manager.c - prise en compte d'une syntaxe du langage d'assemblage
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,14 +21,14 @@
*/
-#include "hooks.h"
+#include "manager.h"
#include <malloc.h>
#include <string.h>
-#include "helpers.h"
+#include "../helpers.h"
diff --git a/tools/d2c/hooks.h b/tools/d2c/hooks/manager.h
index 5dbf223..e3d51b6 100644
--- a/tools/d2c/hooks.h
+++ b/tools/d2c/hooks/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * hooks.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage
+ * manager.h - prototypes pour la prise en compte d'une hookse du langage d'assemblage
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,8 +21,8 @@
*/
-#ifndef _TOOLS_HOOKS_H
-#define _TOOLS_HOOKS_H
+#ifndef _TOOLS_D2C_HOOKS_MANAGER_H
+#define _TOOLS_D2C_HOOKS_MANAGER_H
#include <stdbool.h>
@@ -48,4 +48,4 @@ bool write_hook_functions(const instr_hooks *, int);
-#endif /* _TOOLS_HOOKS_H */
+#endif /* _TOOLS_D2C_HOOKS_MANAGER_H */
diff --git a/tools/d2c/hooks/tokens.l b/tools/d2c/hooks/tokens.l
new file mode 100644
index 0000000..6aebe87
--- /dev/null
+++ b/tools/d2c/hooks/tokens.l
@@ -0,0 +1,26 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option noyy_top_state
+
+
+%%
+
+
+" " { }
+
+[ \t\n]+ { }
+[a-z_][a-z0-9_]* { yylvalp->string = strdup(yytext); return NAME; }
+"=" { return EQ; }
+
+
+%%
diff --git a/tools/d2c/manual.h b/tools/d2c/manual.h
new file mode 100644
index 0000000..1402ca5
--- /dev/null
+++ b/tools/d2c/manual.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * manual.h - définitions de macros pour la lecture manuelle de lexèmes
+ *
+ * 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_MANUAL_H
+#define _TOOLS_D2C_MANUAL_H
+
+
+#define read_block(tmp) \
+ ({ \
+ unsigned int __depth; \
+ bool __is_string; \
+ char *__iter; \
+ \
+ __depth = 1; \
+ __is_string = false; \
+ \
+ for (__iter = temp; __depth > 0; __iter += (__depth > 0 ? 1 : 0)) \
+ { \
+ *__iter = input(); \
+ \
+ switch (*__iter) \
+ { \
+ case '"': \
+ __is_string = !__is_string; \
+ break; \
+ \
+ case '{': \
+ if (!__is_string) __depth++; \
+ break; \
+ \
+ case '}': \
+ if (!__is_string) __depth--; \
+ break; \
+ \
+ } \
+ \
+ } \
+ \
+ *__iter = '\0'; \
+ \
+ printf("\n\nBLOCK\n''''\n%s\n''''\n\n", temp); \
+ })
+
+
+#endif /* _TOOLS_D2C_MANUAL_H */
diff --git a/tools/d2c/pproc.h b/tools/d2c/pproc.h
index 6675fa1..2a7b6c8 100644
--- a/tools/d2c/pproc.h
+++ b/tools/d2c/pproc.h
@@ -21,8 +21,8 @@
*/
-#ifndef _TOOLS_PPROC_H
-#define _TOOLS_PPROC_H
+#ifndef _TOOLS_D2C_PPROC_H
+#define _TOOLS_D2C_PPROC_H
#include <sys/types.h>
@@ -64,4 +64,4 @@ const char *find_macro(const pre_processor *, const char *);
-#endif /* _TOOLS_PPROC_H */
+#endif /* _TOOLS_D2C_PPROC_H */
diff --git a/tools/d2c/qckcall.h b/tools/d2c/qckcall.h
index 42aa3db..2d16048 100644
--- a/tools/d2c/qckcall.h
+++ b/tools/d2c/qckcall.h
@@ -21,18 +21,17 @@
*/
-#ifndef _TOOLS_QCKCALL_H
-#define _TOOLS_QCKCALL_H
+#ifndef _TOOLS_D2C_QCKCALL_H
+#define _TOOLS_D2C_QCKCALL_H
#include <stdbool.h>
-
-#include "args.h"
-#include "conv.h"
-#include "bits.h"
#include "pproc.h"
+#include "args/manager.h"
+#include "bits/manager.h"
+#include "conv/manager.h"
@@ -44,4 +43,4 @@ bool checked_call_instr_func(const char *, const arg_list_t *, int, const coding
-#endif /* _TOOLS_QCKCALL_H */
+#endif /* _TOOLS_D2C_QCKCALL_H */
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.c b/tools/d2c/rules/manager.c
index d527454..f30559e 100644
--- a/tools/d2c/rules.c
+++ b/tools/d2c/rules/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * rules.h - prototypes pour les variations de décodage selon certaines conditions
+ * manager.h - prototypes pour les variations de décodage selon certaines conditions
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,7 +21,7 @@
*/
-#include "rules.h"
+#include "manager.h"
#include <malloc.h>
@@ -29,8 +29,8 @@
#include <string.h>
-#include "helpers.h"
-#include "qckcall.h"
+#include "../helpers.h"
+#include "../qckcall.h"
diff --git a/tools/d2c/rules.h b/tools/d2c/rules/manager.h
index cac6a55..f8ff2d6 100644
--- a/tools/d2c/rules.h
+++ b/tools/d2c/rules/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * rules.h - prototypes pour les variations de décodage selon certaines conditions
+ * manager.h - prototypes pour les variations de décodage selon certaines conditions
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,14 +21,14 @@
*/
-#ifndef _TOOLS_RULES_H
-#define _TOOLS_RULES_H
+#ifndef _TOOLS_D2C_RULES_MANAGER_H
+#define _TOOLS_D2C_RULES_MANAGER_H
-#include "args.h"
-#include "bits.h"
-#include "conv.h"
-#include "pproc.h"
+#include "../pproc.h"
+#include "../args/manager.h"
+#include "../bits/manager.h"
+#include "../conv/manager.h"
@@ -117,4 +117,4 @@ bool write_decoding_rules(decoding_rules *, CondActionType, int, const char *, c
-#endif /* _TOOLS_RULES_H */
+#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(); }
+
+
+%%
diff --git a/tools/d2c/spec.h b/tools/d2c/spec.h
index 39bfdb7..e09aa49 100644
--- a/tools/d2c/spec.h
+++ b/tools/d2c/spec.h
@@ -21,19 +21,19 @@
*/
-#ifndef _TOOLS_SPEC_H
-#define _TOOLS_SPEC_H
+#ifndef _TOOLS_D2C_SPEC_H
+#define _TOOLS_D2C_SPEC_H
#include <stdbool.h>
-#include "bits.h"
-#include "conv.h"
-#include "hooks.h"
#include "pproc.h"
-#include "rules.h"
-#include "syntax.h"
+#include "bits/manager.h"
+#include "conv/manager.h"
+#include "hooks/manager.h"
+#include "rules/manager.h"
+#include "syntax/manager.h"
@@ -73,4 +73,4 @@ bool write_encoding_spec_disass(const encoding_spec *, int, const char *, const
-#endif /* _TOOLS_SPEC_H */
+#endif /* _TOOLS_D2C_SPEC_H */
diff --git a/tools/d2c/syntax/Makefile.am b/tools/d2c/syntax/Makefile.am
new file mode 100644
index 0000000..716f5da
--- /dev/null
+++ b/tools/d2c/syntax/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 syntax_
+
+AM_LFLAGS = -P syntax_ -o lex.yy.c --header-file=tokens.h \
+ -Dyylval=syntax_lval -Dyyget_lineno=syntax_get_lineno \
+ -Dyy_scan_string=syntax__scan_string \
+ -Dyy_delete_buffer=syntax__delete_buffer
+
+AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS)
+
+
+noinst_LTLIBRARIES = libd2csyntax.la
+
+.NOTPARALLEL: $(noinst_LTLIBRARIES)
+
+libd2csyntax_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/syntax/decl.h b/tools/d2c/syntax/decl.h
new file mode 100644
index 0000000..38e5f6d
--- /dev/null
+++ b/tools/d2c/syntax/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_SYNTAX_DECL_H
+#define _TOOLS_D2C_SYNTAX_DECL_H
+
+
+#include "manager.h"
+
+
+
+/* Interprête des données liées à une définition de syntaxe. */
+bool load_syntax_from_raw_line(asm_syntax *, const char *);
+
+
+
+#endif /* _TOOLS_D2C_SYNTAX_DECL_H */
diff --git a/tools/d2c/syntax/grammar.y b/tools/d2c/syntax/grammar.y
new file mode 100644
index 0000000..3952b9a
--- /dev/null
+++ b/tools/d2c/syntax/grammar.y
@@ -0,0 +1,109 @@
+
+%{
+
+#include "tokens.h"
+
+
+/* Affiche un message d'erreur suite à l'analyse en échec. */
+static int yyerror(asm_syntax *, char *);
+
+%}
+
+
+%code requires {
+
+#include "decl.h"
+
+}
+
+
+%union {
+
+ char *string; /* Chaîne de caractères */
+
+}
+
+
+%define api.pure full
+
+%parse-param { asm_syntax *syntax }
+
+%code provides {
+
+#define YY_DECL \
+ int syntax_lex(YYSTYPE *yylvalp)
+
+YY_DECL;
+
+}
+
+
+%token OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
+
+%type <string> OPERAND_NAME OPERAND_INTERNAL OPERAND_VISIBLE
+
+
+%%
+
+
+operands : /* empty */
+ | operands OPERAND_NAME { register_syntax_item(syntax, $2, SIT_KEYWORD); }
+ | operands OPERAND_INTERNAL { register_syntax_item(syntax, $2, SIT_INT_OPERAND); }
+ | operands OPERAND_VISIBLE { register_syntax_item(syntax, $2, SIT_EXT_OPERAND); }
+
+
+%%
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = 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(asm_syntax *syntax, char *msg)
+{
+ printf("syntax yyerror line %d: %s\n", yyget_lineno(), msg);
+
+ return 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : syntax = structure à constituer à partir de données lues. *
+* raw = données brutes à analyser. *
+* *
+* Description : Interprête des données liées à une définition de syntaxe. *
+* *
+* Retour : true si l'opération s'est bien déroulée, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool load_syntax_from_raw_line(asm_syntax *syntax, 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(syntax);
+
+ result = (status == 0);
+
+ yy_delete_buffer(state);
+
+ return result;
+
+}
diff --git a/tools/d2c/syntax.c b/tools/d2c/syntax/manager.c
index 96fffc5..ae2a71b 100644
--- a/tools/d2c/syntax.c
+++ b/tools/d2c/syntax/manager.c
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * syntax.c - prise en compte d'une syntaxe du langage d'assemblage
+ * manager.c - prise en compte d'une syntaxe du langage d'assemblage
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,14 +21,14 @@
*/
-#include "syntax.h"
+#include "manager.h"
#include <malloc.h>
#include <string.h>
-#include "helpers.h"
+#include "../helpers.h"
diff --git a/tools/d2c/syntax.h b/tools/d2c/syntax/manager.h
index 70b3609..1ae1a24 100644
--- a/tools/d2c/syntax.h
+++ b/tools/d2c/syntax/manager.h
@@ -1,6 +1,6 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * syntax.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage
+ * manager.h - prototypes pour la prise en compte d'une syntaxe du langage d'assemblage
*
* Copyright (C) 2014 Cyrille Bagard
*
@@ -21,16 +21,16 @@
*/
-#ifndef _TOOLS_SYNTAX_H
-#define _TOOLS_SYNTAX_H
+#ifndef _TOOLS_D2C_SYNTAX_MANAGER_H
+#define _TOOLS_D2C_SYNTAX_MANAGER_H
#include <stdbool.h>
-#include "bits.h"
-#include "conv.h"
-#include "pproc.h"
+#include "../pproc.h"
+#include "../bits/manager.h"
+#include "../conv/manager.h"
@@ -70,4 +70,4 @@ bool define_syntax_items(const asm_syntax *, int, const char *, const coding_bit
-#endif /* _TOOLS_SYNTAX_H */
+#endif /* _TOOLS_D2C_SYNTAX_MANAGER_H */
diff --git a/tools/d2c/syntax/tokens.l b/tools/d2c/syntax/tokens.l
new file mode 100644
index 0000000..ab1b0f3
--- /dev/null
+++ b/tools/d2c/syntax/tokens.l
@@ -0,0 +1,39 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+%option noyywrap
+%option nounput
+%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+%x named
+%x internal
+%x visible
+
+
+%%
+
+
+" " { }
+
+"\"" { yy_push_state(named); }
+<named>[^ \"]+ { yylvalp->string = strdup(yytext); return OPERAND_NAME; }
+<named>"\"" { yy_pop_state(); }
+
+"{" { yy_push_state(internal); }
+<internal>[^ }]+ { yylvalp->string = strdup(yytext); return OPERAND_INTERNAL; }
+<internal>"}" { yy_pop_state(); }
+
+"<" { yy_push_state (visible); }
+<visible>[^ >]+ { yylvalp->string = strdup(yytext); return OPERAND_VISIBLE; }
+<visible>">" { yy_pop_state(); }
+
+
+%%
diff --git a/tools/d2c/tokens.l b/tools/d2c/tokens.l
new file mode 100644
index 0000000..e48d079
--- /dev/null
+++ b/tools/d2c/tokens.l
@@ -0,0 +1,132 @@
+
+%top {
+
+#include "grammar.h"
+
+}
+
+
+
+%{
+
+ //typedef struct _rented_coder rented_coder;
+
+
+//#include "d2c-d2c_gram.h"
+
+#include <ctype.h>
+#include <string.h>
+
+
+#include "manual.h"
+
+
+
+%}
+
+%option noyywrap
+%option nounput
+ //%option noinput
+%option yylineno
+%option stack
+%option noyy_top_state
+
+ //%option reentrant
+ //%option bison-bridge
+
+/* %option bison-bridge */
+/* %option bison-locations */
+/* %option ecs */
+/* %option nodefault */
+/* %option noyywrap */
+/* %option reentrant */
+
+
+%x comments
+
+%x ins_name try_details ins_details
+%x encoding encoding_type encoding_content
+
+%x encoding_bits encoding_bits_size
+
+%x raw_line
+
+
+
+%%
+
+
+[ \t\n]+ { }
+
+"/*" { BEGIN(comments); }
+<comments>"*/" { BEGIN(INITIAL); }
+<comments>[^*\n] { }
+<comments>"Copyright"[^\n]* { yylvalp->string = strdup(yytext); return COPYRIGHT; }
+<comments>"*" { }
+<comments>"\n" { }
+
+
+"@title" { BEGIN(ins_name); return TITLE; }
+
+<ins_name>[ ][A-Za-z-]+ { yylvalp->string = strdup(yytext + 1); BEGIN(try_details); return INS_NAME; }
+<try_details>[ ,/] { BEGIN(ins_details); }
+<try_details>[\n] { BEGIN(INITIAL); }
+
+<ins_details>[^\n]* { yylvalp->cstring = yytext; return INS_DETAILS; }
+<ins_details>[\n] { BEGIN(INITIAL); }
+
+
+
+"@encoding" { BEGIN(encoding); return ENCODING; }
+
+<encoding>[ ] { }
+<encoding>"(" { BEGIN(encoding_type); }
+
+<encoding_type>[A-Za-z] { yylvalp->string = strdup(yytext); return TYPE; }
+<encoding_type>[0-9]+ { yylvalp->integer = atoi(yytext); return NUMBER; }
+<encoding_type>")" { BEGIN(encoding); }
+
+<encoding>"{" { BEGIN(encoding_content); }
+<encoding_content>[ \t\n]+ { }
+<encoding_content>"}" { BEGIN(INITIAL); }
+
+
+
+<encoding_content>"@half " { yy_push_state(raw_line); return HALF; }
+<encoding_content>"@word " { yy_push_state(raw_line); return WORD; }
+
+
+<raw_line>[^\n]+ { yylvalp->cstring = yytext; return RAW_LINE; }
+<raw_line>"\n" { yy_pop_state(); }
+
+
+
+
+<encoding_content>"@syntax " { yy_push_state(raw_line); return SYNTAX; }
+
+
+
+
+
+<encoding_content>"@conv" { return CONV; }
+
+
+
+
+<encoding_content>"{" {
+ read_block(temp);
+ yylvalp->cstring = temp; return RAW_BLOCK;
+ }
+
+
+
+
+
+
+
+<encoding_content>"@hooks" { return HOOKS; }
+
+<encoding_content>"@rules" { return RULES; }
+
+
+%%