summaryrefslogtreecommitdiff
path: root/src/format/mangling
diff options
context:
space:
mode:
Diffstat (limited to 'src/format/mangling')
-rw-r--r--src/format/mangling/Makefile.am2
-rw-r--r--src/format/mangling/itanium_gram.y515
-rw-r--r--src/format/mangling/itanium_tok.l12
3 files changed, 454 insertions, 75 deletions
diff --git a/src/format/mangling/Makefile.am b/src/format/mangling/Makefile.am
index 80c0757..994919d 100644
--- a/src/format/mangling/Makefile.am
+++ b/src/format/mangling/Makefile.am
@@ -14,7 +14,7 @@ libformatmangling_la_SOURCES = \
libformatmangling_la_LDFLAGS =
-INCLUDES = $(LIBGTK_CFLAGS)
+INCLUDES = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
AM_CPPFLAGS =
diff --git a/src/format/mangling/itanium_gram.y b/src/format/mangling/itanium_gram.y
index da1ea10..e6078b0 100644
--- a/src/format/mangling/itanium_gram.y
+++ b/src/format/mangling/itanium_gram.y
@@ -32,6 +32,9 @@ typedef struct _itanium_demangler
size_t id_allocated; /* Taille allouée en mémoire */
size_t id_used; /* Longueur de la chaîne */
+ bool use_templates; /* Utilisation des gabarits */
+ GSList *routines; /* Routines en cours de maj */
+
} itanium_demangler;
@@ -50,6 +53,27 @@ void reset_itanium_identifier_building(itanium_demangler *);
void build_itanium_identifier(itanium_demangler *, char);
+/* Place sous le feu des projecteurs une nouvelle routine. */
+static GBinRoutine *push_routine(itanium_demangler *, GBinRoutine *);
+
+/* Remet une ancienne routine sous le feu des projecteurs. */
+static GBinRoutine *pop_routine(itanium_demangler *);
+
+
+
+/* Liste de substitutions */
+typedef GSList substi_list;
+
+/* Met en place une liste pour recueillir les substitutions. */
+static substi_list *create_substitution_list(void);
+
+/* Ajoute un élément dans une liste de substitutions. */
+static void add_substitution_item(substi_list *, GOpenidaType *);
+
+/* Fournit le nième élément d'une liste de substitutions. */
+static GOpenidaType *get_substitution_item(substi_list *, guint);
+
+
/* Borne la longueur d'une chaîne à lire. */
@@ -90,26 +114,44 @@ char *strmerge(char *str1, const char *sep, char *str2);
%union {
+ struct
+ {
+ union
+ {
+ char *str;
+ void/*GOpenidaType*/ *type;
+ };
+ int/*bool*/ is_string;
+
+ } str_or_type;
+
char car;
char *text;
unsigned int val;
short/*s16_t*/ s16_val;
+ void /*GOpenidaType*/ *type;
+ void /*GTemplateType*/ *templtype;
+
void/*simple_variable*/ *simple;
void/*complex_variable*/ *complex;
void/*variable*/ *var;
int/*VariableQualifier*/ qual;
+ void/*GSList*/ *slist;
+
}
%parse-param { itanium_demangler *demangler }
+%parse-param { substi_list *substitutions }
%parse-param { GBinRoutine *routine }
+
%token ITANIUM_SIGNATURE
-%token EE NN II
+%token EE NN II FF LL
%token C1 C2 C3 D1 D2 D3
@@ -130,6 +172,9 @@ char *strmerge(char *str1, const char *sep, char *str2);
%token OPER_LESS_EQ OPER_GREATER_EQ OPER_NOT OPER_AND_AND OPER_OR_OR OPER_PLUS_PLUS OPER_MINUS_MINUS
%token OPER_COMMA OPER_PRIV_MEMB OPER_POINTER_TO OPER_CLASS OPER_INDEX
+%token SUBSTI_FIRST SUBSTI_N
+
+%token TPARAM_FIRST TPARAM_N
%token NUMBER CHAR
@@ -161,29 +206,37 @@ char *strmerge(char *str1, const char *sep, char *str2);
%type <s16_val> DEC_16
+%type <str_or_type> name
+
+%type <text> unscoped_name
+%type <type> nested_name
+
+%type <templtype> unscoped_template_name
-%type <text> name unscoped_name unscoped_template_name nested_name
%type <text> unqualified_name operator_name
-%type <text> prefix source_name
+%type <text> prefix template_prefix source_name
+
+%type <type> template_param template_template_param
-%type <var> type
+%type <type> function_type type
%type <qual> qualifiers
%type <simple> builtin_type
-%type <complex> class_enum_type
+%type <type> class_enum_type
+
+%type <slist> template_args template_arg_list
+%type <type> template_arg expr_primary
-%type <text> template_args template_arg_list template_arg
%type <text> substitution
%type <car> CHAR
-%type <val> NUMBER
-
+%type <val> NUMBER SUBSTI_N TPARAM_N
%{
@@ -204,21 +257,24 @@ extern void yy_delete_buffer(YY_BUFFER_STATE);
%%
+
+
input:
ITANIUM_SIGNATURE encoding
;
encoding:
- name bare_function_type
+ name { $1.is_string ? g_binary_routine_set_name(routine, $1.str) : g_binary_routine_set_name_from_type(routine, $1.type); }
+ bare_function_type { ; }
;
name:
- nested_name { $$ = $1; g_binary_routine_set_name(routine, $1); }
- | unscoped_name { $$ = $1; g_binary_routine_set_name(routine, $1); }
- | unscoped_template_name template_args { $$ = stradd($1, $2); /* TODO : merge -> free */ }
+ nested_name { $$.type = $1; $$.is_string = false; }
+ | unscoped_name { $$.str = $1; $$.is_string = true; }
+ | unscoped_template_name template_args { $$.type = $1; $$.is_string = false; g_template_type_add_params($1, $2); }
;
unscoped_name:
@@ -227,27 +283,49 @@ unscoped_name:
;
unscoped_template_name:
- unscoped_name { $$ = $1; }
- | substitution { $$ = $1; }
+ unscoped_name { $$ = g_template_type_new($1, NULL); add_substitution_item(substitutions, $$); }
+ | substitution {
+ $$ = NULL;/*g_openida_type_to_string($1)*/;
+ /*printf("unscoped sub name :: %s\n", $$);
+ g_object_unref(G_OBJECT($1));*/
+ }
;
nested_name:
- NN prefix unqualified_name EE { $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2); }
+ NN prefix unqualified_name EE {
+ $$ = ($3 != NULL ? strmerge($2, "::", $3) : $2);
+ $$ = g_class_enum_type_new(CET_UNKNOWN, $$);
+ }
+ | NN template_prefix template_args EE { $$ = g_template_type_new($2, $3); }
;
prefix:
- /* vide */ { $$ = NULL; printf("passage E\n"); }
+ /* vide */ { $$ = NULL; /*printf("passage E\n")*/; }
| prefix unqualified_name { $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); }
- | substitution { $$ = $1; }
+ | template_prefix template_args { $$ = g_template_type_new($1, $2); $$ = g_openida_type_to_string($$); /* FIXME : retourner un type ! */}
+ | substitution {
+ $$ = g_openida_type_to_string($1);
+ printf("prefix substi :: %s\n", $$);
+ g_object_unref(G_OBJECT($1));
+ }
+ ;
+
+template_prefix:
+ prefix unqualified_name { $$ = ($2 != NULL ? strmerge($1, "::", $2) : $1); }
+ | template_param {
+ $$ = g_openida_type_to_string($1);
+ g_object_unref(G_OBJECT($1));
+ }
;
+
unqualified_name:
operator_name { printf("dup :: '%s'\n", $1); fflush(NULL) ;$$ = strdup($1) ; }
| ctor_dtor_name { printf("passage C\n"); $$ = NULL; }
@@ -258,7 +336,7 @@ unqualified_name:
source_name:
NUMBER { set_itanium_text_length($1); reset_itanium_identifier_building(demangler); }
- identifier { $$ = strdup(demangler->identifier); }
+ identifier { $$ = strdup(demangler->identifier); printf("==source name== :: %s\n", $$); }
;
identifier:
@@ -330,92 +408,154 @@ ctor_dtor_name:
;
+function_type:
+ FF { routine = push_routine(demangler, routine); }
+ bare_function_type EE {
+ $$ = g_encapsulated_type_new(ECT_ROUTINE, routine);
+ routine = pop_routine(demangler);
+ if (routine == NULL) YYERROR;
+ }
+ ;
+
+
type:
- builtin_type { $$ = create_var_from_simple_one($1); }
- | class_enum_type { $$ = create_var_from_complex_one($1); }
- | substitution { $$ = create_var_from_complex_one(create_class_enum_var($1)); }
- | qualifiers type { $$ = $2; add_qualifier_to_var($2, $1); }
- | TP type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_POINTER, $2)); }
- | TR type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_REFERENCE, $2)); }
- | TO type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_RVALUE_REF, $2)); }
- | TC type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_COMPLEX, $2)); }
- | TG type { $$ = create_var_from_complex_one(create_encapsulated_var(ECT_IMAGINARY, $2)); }
+ builtin_type { $$ = $1; printf("builtin '%s'\n", g_openida_type_to_string($1)); }
+ | class_enum_type { $$ = $1; add_substitution_item(substitutions, $1); }
+ | substitution { $$ = $1; }
+ | template_param { $$ = $1; }
+ | template_template_param template_args {
+ $$ = g_template_type_new(g_openida_type_to_string($1), NULL);
+ g_object_unref($1);
+ g_template_type_add_params($$, $2);
+ }
+ | function_type { $$ = $1; }
+ | qualifiers type {
+ $$ = g_openida_type_dup($2);
+ g_openida_type_add_qualifier($$, $1);
+ add_substitution_item(substitutions, $$);
+ }
+ | TP type { $$ = g_encapsulated_type_new(ECT_POINTER, $2); add_substitution_item(substitutions, $$); }
+ | TR type { $$ = g_encapsulated_type_new(ECT_REFERENCE, $2); add_substitution_item(substitutions, $$); }
+ | TO type { $$ = g_encapsulated_type_new(ECT_RVALUE_REF, $2); add_substitution_item(substitutions, $$); }
+ | TC type { $$ = g_encapsulated_type_new(ECT_COMPLEX, $2); add_substitution_item(substitutions, $$); }
+ | TG type { $$ = g_encapsulated_type_new(ECT_IMAGINARY, $2); add_substitution_item(substitutions, $$); }
;
qualifiers:
- QR { $$ = VQF_RESTRICT; }
- | QV { $$ = VQF_VOLATILE; }
- | QK { $$ = VQF_CONST; }
+ QR { $$ = TQF_RESTRICT; }
+ | QV { $$ = TQF_VOLATILE; }
+ | QK { $$ = TQF_CONST; }
;
builtin_type:
- V { $$ = create_typed_simple_var(BTP_VOID); }
- | W { $$ = create_typed_simple_var(BTP_WCHAR_T); }
- | B { $$ = create_typed_simple_var(BTP_BOOL); }
- | C { $$ = create_typed_simple_var(BTP_CHAR); }
- | A { $$ = create_typed_simple_var(BTP_SCHAR); }
- | H { $$ = create_typed_simple_var(BTP_UCHAR); }
- | S { $$ = create_typed_simple_var(BTP_SHORT); }
- | T { $$ = create_typed_simple_var(BTP_USHORT); }
- | I { $$ = create_typed_simple_var(BTP_INT); }
- | J { $$ = create_typed_simple_var(BTP_UINT); }
- | L { $$ = create_typed_simple_var(BTP_LONG); }
- | M { $$ = create_typed_simple_var(BTP_ULONG); }
- | X { $$ = create_typed_simple_var(BTP_LONG_LONG); }
- | Y { $$ = create_typed_simple_var(BTP_ULONG_LONG); }
- | N { $$ = create_typed_simple_var(BTP_INT128); }
- | O { $$ = create_typed_simple_var(BTP_UINT128); }
- | F { $$ = create_typed_simple_var(BTP_FLOAT); }
- | D { $$ = create_typed_simple_var(BTP_DOUBLE); }
- | E { $$ = create_typed_simple_var(BTP_LONG_DOUBLE); }
- | G { $$ = create_typed_simple_var(BTP_FLOAT128); }
- | Z { $$ = create_typed_simple_var(BTP_ELLIPSIS); }
- | DD { $$ = create_typed_simple_var(BTP_754R_64); }
- | DE { $$ = create_typed_simple_var(BTP_754R_128); }
- | DF { $$ = create_typed_simple_var(BTP_754R_32); }
- | DH { $$ = create_typed_simple_var(BTP_754R_16); }
- | DI { $$ = create_typed_simple_var(BTP_CHAR32_T); }
- | DS { $$ = create_typed_simple_var(BTP_CHAR16_T); }
- | U source_name { $$ = create_typed_simple_var(BTP_OTHER); /* TODO */ ; free($2); }
+ V { $$ = g_basic_type_new(BTP_VOID); }
+ | W { $$ = g_basic_type_new(BTP_WCHAR_T); }
+ | B { $$ = g_basic_type_new(BTP_BOOL); }
+ | C { $$ = g_basic_type_new(BTP_CHAR); }
+ | A { $$ = g_basic_type_new(BTP_SCHAR); }
+ | H { $$ = g_basic_type_new(BTP_UCHAR); }
+ | S { $$ = g_basic_type_new(BTP_SHORT); }
+ | T { $$ = g_basic_type_new(BTP_USHORT); }
+ | I { $$ = g_basic_type_new(BTP_INT); }
+ | J { $$ = g_basic_type_new(BTP_UINT); }
+ | L { $$ = g_basic_type_new(BTP_LONG); }
+ | M { $$ = g_basic_type_new(BTP_ULONG); }
+ | X { $$ = g_basic_type_new(BTP_LONG_LONG); }
+ | Y { $$ = g_basic_type_new(BTP_ULONG_LONG); }
+ | N { $$ = g_basic_type_new(BTP_INT128); }
+ | O { $$ = g_basic_type_new(BTP_UINT128); }
+ | F { $$ = g_basic_type_new(BTP_FLOAT); }
+ | D { $$ = g_basic_type_new(BTP_DOUBLE); }
+ | E { $$ = g_basic_type_new(BTP_LONG_DOUBLE); }
+ | G { $$ = g_basic_type_new(BTP_FLOAT128); }
+ | Z { $$ = g_basic_type_new(BTP_ELLIPSIS); }
+ | DD { $$ = g_basic_type_new(BTP_754R_64); }
+ | DE { $$ = g_basic_type_new(BTP_754R_128); }
+ | DF { $$ = g_basic_type_new(BTP_754R_32); }
+ | DH { $$ = g_basic_type_new(BTP_754R_16); }
+ | DI { $$ = g_basic_type_new(BTP_CHAR32_T); }
+ | DS { $$ = g_basic_type_new(BTP_CHAR16_T); }
+ | U source_name { $$ = g_basic_type_new(BTP_OTHER); /* TODO */ ; free($2); }
;
bare_function_type:
- bare_function_type type { g_binary_routine_add_arg(routine, $2); }
- | type { g_binary_routine_add_arg(routine, $1); }
+ bare_function_type type { g_binary_routine_add_arg(routine, g_binary_variable_new($2)); }
+ | type {
+ if (demangler->use_templates)
+ g_binary_routine_set_return_type(routine, $1);
+ else
+ g_binary_routine_add_arg(routine, g_binary_variable_new($1));
+ }
;
class_enum_type:
- name { $$ = create_class_enum_var($1); }
+ name { $$ = $1.is_string ? g_class_enum_type_new(CET_UNKNOWN, $1.str) : $1.type; }
;
+template_param:
+ TPARAM_FIRST {
+ const GOpenidaType *type = g_binary_routine_get_type_from_name(routine);
+ if (G_IS_TEMPLATE_TYPE(type))
+ $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), 0);
+ else $$ = NULL;
+ if ($$ == NULL) YYERROR;
+ }
+ | TPARAM_N {
+ const GOpenidaType *type = g_binary_routine_get_type_from_name(routine);
+ if (G_IS_TEMPLATE_TYPE(type))
+ $$ = g_template_type_get_param(G_TEMPLATE_TYPE(type), $1 + 1);
+ else $$ = NULL;
+ if ($$ == NULL) YYERROR;
+ }
+ ;
+
+template_template_param:
+ template_param { $$ = $1; }
+ | substitution { $$ = $1; }
+ ;
+
template_args:
- II template_arg_list EE { printf("passage I\n"); $$ = stradd(strprep($2, "<"), ">"); }
+ use_templates template_arg_list EE { $$ = $2; }
+ ;
+
+use_templates:
+ II { printf("new template !!!\n"); demangler->use_templates = true; }
;
template_arg_list:
- template_arg_list template_arg { $$ = strmerge($1, ", ", $2); }
- | template_arg { $$ = $1; }
+ template_arg_list template_arg { $$ = g_slist_prepend($1, $2); }
+ | template_arg { $$ = g_slist_prepend(NULL, $1); }
+ | template_args { g_class_enum_type_new(CET_UNKNOWN, "template params"); }
;
template_arg:
- type { $$ = var_to_string($1); delete_var($1); }
+ type { $$ = $1; }
+ | expr_primary { $$ = $1; }
;
+
+expr_primary:
+ LL type NUMBER EE { $$ = $2; }
+ ;
+
+
substitution:
- ST { $$ = strdup("std"); }
- | SA { $$ = strdup("std::allocator"); }
- | SB { $$ = strdup("std::basic_string"); }
- | SS { $$ = strdup("std::string"); }
- | SI { $$ = strdup("std::istream"); }
- | SO { $$ = strdup("std::ostream"); }
- | SD { $$ = strdup("std::iostream"); }
+ ST { $$ = g_class_enum_type_new(CET_CLASS, "std"); }
+ | SA { $$ = g_class_enum_type_new(CET_CLASS, "std::allocator"); }
+ | SB { $$ = g_class_enum_type_new(CET_CLASS, "std::basic_string"); }
+ | SS { $$ = g_class_enum_type_new(CET_CLASS, "std::string"); }
+ | SI { $$ = g_class_enum_type_new(CET_CLASS, "std::istream"); }
+ | SO { $$ = g_class_enum_type_new(CET_CLASS, "std::ostream"); }
+ | SD { $$ = g_class_enum_type_new(CET_CLASS, "std::iostream"); }
+ | SUBSTI_FIRST { $$ = get_substitution_item(substitutions, 0); if ($$ == NULL) YYERROR; }
+ | SUBSTI_N { $$ = get_substitution_item(substitutions, $1 + 1); if ($$ == NULL) YYERROR; }
;
@@ -516,15 +656,23 @@ bool can_be_itanium_demangled(itanium_demangler *itanium, const char *name)
GBinRoutine *demangle_itanium_routine(itanium_demangler *demangler, const char *name)
{
GBinRoutine *result; /* Construction à retourner */
+ substi_list *substitutions; /* Liste de substitutions */
YY_BUFFER_STATE buffer; /* Tampon pour bison */
int ret; /* Bilan de l'appel */
+ /* TODO : reset ! */
+ demangler->use_templates = false;
+
result = g_binary_routine_new();
+ substitutions = create_substitution_list();
+
buffer = yy_scan_string(name);
- ret = yyparse(demangler, result);
+ ret = yyparse(demangler, substitutions, result);
yy_delete_buffer(buffer);
+ //delete(substi_list *substitutions);
+
if (ret != 0)
{
/*delete_binary_routine(result); FIXME */
@@ -581,3 +729,224 @@ void build_itanium_identifier(itanium_demangler *demangler, char value)
demangler->identifier[demangler->id_used] = 0;
}
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à mettre à jour. *
+* previous = routine à sauvegarder. *
+* *
+* Description : Place sous le feu des projecteurs une nouvelle routine. *
+* *
+* Retour : Nouvelle routine à compléter. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBinRoutine *push_routine(itanium_demangler *demangler, GBinRoutine *previous)
+{
+ GBinRoutine *result; /* Routine nouvelle à renvoyer */
+
+ result = g_binary_routine_new();
+
+ demangler->routines = g_slist_append(demangler->routines, previous);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à mettre à jour. *
+* *
+* Description : Remet une ancienne routine sous le feu des projecteurs. *
+* *
+* Retour : Routine sauvegardée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GBinRoutine *pop_routine(itanium_demangler *demangler)
+{
+ GBinRoutine *result; /* Routine nouvelle à renvoyer */
+ GSList *last; /* Dernier élément */
+
+ last = g_slist_last(demangler->routines);
+
+ if (last == NULL) result = NULL;
+ else
+ {
+ result = G_BIN_ROUTINE(last->data);
+ demangler->routines = g_slist_remove(demangler->routines, result);
+ }
+
+ return result;
+
+}
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Met en place une liste pour recueillir les substitutions. *
+* *
+* Retour : Nouvelle liste vierge pour les substitutions. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static substi_list *create_substitution_list(void)
+{
+ return g_slist_alloc();
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble des substitions enregistrées. *
+* type = nouvel élément à placer dans la liste des substitut°. *
+* *
+* Description : Ajoute un élément dans une liste de substitutions. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void add_substitution_item(substi_list *list, GOpenidaType *type)
+{
+ g_object_ref(G_OBJECT(type));
+
+ printf("push %p\n", type);
+
+ g_slist_append(list, type);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : list = ensemble des substitions enregistrées. *
+* n = indice de l'élément à fournir. *
+* *
+* Description : Fournit le nième élément d'une liste de substitutions. *
+* *
+* Retour : Type prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GOpenidaType *get_substitution_item(substi_list *list, guint n)
+{
+ printf("get [%u] == %p\n", n, g_slist_nth_data(list, n + 1));
+
+ return G_OPENIDA_TYPE(g_slist_nth_data(list, n + 1));
+
+}
+
+
+
+/******************************************************************************
+* *
+* Paramètres : demangler = décodeur à utiliser. *
+* *
+* Description : Procède au test de décodages de chaînes de caractères. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#ifdef DEBUG
+void test_itanium_demangling(itanium_demangler *demangler)
+{
+ GBinRoutine *routine;
+ char *human;
+ char stop;
+
+#define TEST_ITANIUM_MANGLING(name, ref) \
+ do \
+ { \
+ printf(" >> %s\n", name); \
+ routine = demangle_itanium_routine(demangler, name); \
+ if (routine == NULL) \
+ { \
+ printf("Error with %s\n", name); \
+ stop = true; \
+ } \
+ else \
+ { \
+ human = g_binary_routine_to_string(routine); \
+ printf(" >> %s\n", human); \
+ stop = (strcmp(ref, human) != 0); \
+ printf(" >> ok ? %s\n", (!stop ? "oui" : "non")); \
+ if (stop) printf(" >> expected '%s'\n", ref); \
+ free(human); \
+ } \
+ if (stop) goto end_of_test; \
+ else printf("\n"); \
+ } \
+ while (0)
+
+ /**
+ * Tests de :
+ * http://www.codesourcery.com/public/cxx-abi/abi-examples.html#mangling
+ */
+
+ TEST_ITANIUM_MANGLING("_Z1fv", "??? f(void)");
+
+ TEST_ITANIUM_MANGLING("_Z1fi", "??? f(int)");
+
+ TEST_ITANIUM_MANGLING("_Z3foo3bar", "??? foo(bar)");
+
+ TEST_ITANIUM_MANGLING("_Zrm1XS_", "??? %(X, X)");
+
+ TEST_ITANIUM_MANGLING("_ZplR1XS0_", "??? +(X &, X &)");
+
+ TEST_ITANIUM_MANGLING("_ZlsRK1XS1_", "??? <<(const X &, const X &)");
+
+ TEST_ITANIUM_MANGLING("_Z1fIiEvi", "void f<int>(int)");
+
+ TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvS0_", "void first<Duo>(Duo)");
+
+ TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvT_", "void first<Duo>(Duo)");
+
+ TEST_ITANIUM_MANGLING("_Z3fooIiPFidEiEvv", "void foo<int, int (*)(double), int>(void)");
+
+ TEST_ITANIUM_MANGLING("_ZN6System5Sound4beepEv", "??? System::Sound::beep(void)");
+
+ TEST_ITANIUM_MANGLING("_Z1fI1XE vPV N1AIT_E1TE", "void f<X>(volatile A<X>::T *)");
+
+ //// TODO :: TEST_ITANIUM_MANGLING("_ZngILi42EE v N1A I XplT_Li2EE E 1TE", "");
+
+ TEST_ITANIUM_MANGLING("_Z4makeI7FactoryiE T_IT0_E v", "Factory<int> make<Factory, int>(void)");
+
+ TEST_ITANIUM_MANGLING("_ZlsRSoRKSs", "??? <<(std::ostream &, const std::string &)");
+
+ //TEST_ITANIUM_MANGLING("", "");
+
+ end_of_test:
+
+ ;
+
+}
+#endif
diff --git a/src/format/mangling/itanium_tok.l b/src/format/mangling/itanium_tok.l
index bc5f5f1..e8fb7f1 100644
--- a/src/format/mangling/itanium_tok.l
+++ b/src/format/mangling/itanium_tok.l
@@ -29,6 +29,8 @@ _Z { return ITANIUM_SIGNATURE; }
E { return EE; }
N { return NN; }
I { return II; }
+F { return FF; }
+L { return LL; }
C1 { return C1; }
C2 { return C2; }
@@ -133,13 +135,21 @@ cl { return OPER_CLASS; }
ix { return OPER_INDEX; }
+S_ { return SUBSTI_FIRST; }
+S[0-9a-z]_ { yylval.val = atoi(yytext + 1); return SUBSTI_N; }
+
+T_ { return TPARAM_FIRST; }
+T[0-9]*_ { yylval.val = atoi(yytext + 1); return TPARAM_N; }
+
+
[0-9]+ { yylval.val = atoi(yytext); return NUMBER; }
<identifier>. { if (--itanium_txt_length == 0) BEGIN(INITIAL); yylval.car = *yytext; return CHAR; }
-<*>. { printf("error : '%s'\n", yytext); }
+<*>[ ]
+<*>. { printf("error : '%s'\n", yytext); }
%%