This series: - improves parsing of list of arguments - fixes parsing of qualified pointer to function/method
From: Eric Pouech epouech@codeweavers.com
This allows while unmangling: - to avoid considering them as "real" datatypes in other contexts - to handle better void (which is only supported as single argument in function args list, while is a fully acceptable datatype in template args list)
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/msvcrt/tests/cpp.c | 6 ++++-- dlls/msvcrt/undname.c | 24 ++++++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c index 028af05b2e0..bed1a5d4530 100644 --- a/dlls/msvcrt/tests/cpp.c +++ b/dlls/msvcrt/tests/cpp.c @@ -1330,11 +1330,13 @@ static void test_demangle(void) "__ptr64 __cdecl std::forward<struct `private: static int __cdecl FFIFunctionBinder::call(struct lua_State " "* __ptr64)'::`2'::FFIValue & __ptr64>(struct `private: static int __cdecl FFIFunctionBinder::call(struct " "xlua_State * __ptr64)'::`2'::FFIValue & __ptr64)"}, +/* 153 */ {"?$AAA@XX", "AAA<void,void>"}, +/* 154 */ {"?$AAA@", "AAA<>"}, }; - int i, num_test = ARRAY_SIZE(test); + int i; char* name;
- for (i = 0; i < num_test; i++) + for (i = 0; i < ARRAY_SIZE(test); i++) { name = p__unDName(0, test[i].in, 0, malloc, free, test[i].flags); ok(name != NULL, "%u: unDName failed\n", i); diff --git a/dlls/msvcrt/undname.c b/dlls/msvcrt/undname.c index 55661f21e2b..74856504685 100644 --- a/dlls/msvcrt/undname.c +++ b/dlls/msvcrt/undname.c @@ -365,6 +365,12 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, unsigned int i; const char *p;
+ if (z_term && sym->current[0] == 'X' && sym->current[1] == 'Z') + { + sym->current += 2; + return str_printf(sym, "%cvoid%c", open_char, close_char); + } + str_array_init(&arg_collect);
/* Now come the function arguments */ @@ -378,6 +384,13 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, sym->current++; break; } + if (z_term && sym->current[0] == 'Z') + { + sym->current++; + if (!str_array_push(sym, "...", -1, &arg_collect)) + return NULL; + break; + } /* Handle empty list in variadic template */ if (!z_term && sym->current[0] == '$' && sym->current[1] == '$' && sym->current[2] == 'V') { @@ -386,12 +399,9 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, } if (!demangle_datatype(sym, &ct, IN_ARGS)) return NULL; - /* 'void' terminates an argument list in a function */ - if (z_term && !strcmp(ct.left, "void")) break; if (!str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1, &arg_collect)) return NULL; - if (!strcmp(ct.left, "...")) break; if (z_term && sym->current - p > 1 && sym->args.num < 20) { if (!str_array_push(sym, ct.left ? ct.left : "", -1, &sym->args) || @@ -404,9 +414,7 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, */ if (z_term && *sym->current++ != 'Z') return NULL;
- if (arg_collect.num == 0 || - (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void"))) - return str_printf(sym, "%cvoid%c", open_char, close_char); + if (!arg_collect.num) return str_printf(sym, "%c%c", open_char, close_char); for (i = 1; i < arg_collect.num; i++) { args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]); @@ -859,7 +867,7 @@ static const char* get_simple_type(char c) case 'N': type_string = "double"; break; case 'O': type_string = "long double"; break; case 'X': type_string = "void"; break; - case 'Z': type_string = "..."; break; +/* case 'Z': (...) variadic function arguments. Handled in get_args() */ default: type_string = NULL; break; } return type_string; @@ -910,7 +918,7 @@ static BOOL get_function_signature(struct parsed_symbol* sym, struct function_si if (!get_calling_convention(*sym->current++, &fs->call_conv, &fs->exported, sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) || - !demangle_datatype(sym, &fs->return_ct, FALSE)) + !demangle_datatype(sym, &fs->return_ct, 0)) return FALSE;
if (!(fs->arguments = get_args(sym, TRUE, '(', ')')))
From: Eric Pouech epouech@codeweavers.com
This allows while unmangling: - to avoid considering them as "real" datatypes in other contexts - to handle better void (which is only supported as single argument in function args list, while is a fully acceptable datatype in template args list)
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/msmangle.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/tools/winedump/msmangle.c b/tools/winedump/msmangle.c index 94e91706585..2ac96a3fe5a 100644 --- a/tools/winedump/msmangle.c +++ b/tools/winedump/msmangle.c @@ -260,6 +260,12 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, unsigned int i; const char *p;
+ if (z_term && sym->current[0] == 'X' && sym->current[1] == 'Z') + { + sym->current += 2; + return str_printf(sym, "%cvoid%c", open_char, close_char); + } + str_array_init(&arg_collect);
/* Now come the function arguments */ @@ -273,6 +279,13 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, sym->current++; break; } + if (z_term && sym->current[0] == 'Z') + { + sym->current++; + if (!str_array_push(sym, "...", -1, &arg_collect)) + return NULL; + break; + } /* Handle empty list in variadic template */ if (!z_term && sym->current[0] == '$' && sym->current[1] == '$' && sym->current[2] == 'V') { @@ -281,12 +294,9 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, } if (!demangle_datatype(sym, &ct, IN_ARGS)) return NULL; - /* 'void' terminates an argument list in a function */ - if (z_term && !strcmp(ct.left, "void")) break; if (!str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1, &arg_collect)) return NULL; - if (!strcmp(ct.left, "...")) break; if (z_term && sym->current - p > 1 && sym->args.num < 20) { if (!str_array_push(sym, ct.left ? ct.left : "", -1, &sym->args) || @@ -299,9 +309,7 @@ static char* get_args(struct parsed_symbol* sym, BOOL z_term, */ if (z_term && *sym->current++ != 'Z') return NULL;
- if (arg_collect.num == 0 || - (arg_collect.num == 1 && !strcmp(arg_collect.elts[0], "void"))) - return str_printf(sym, "%cvoid%c", open_char, close_char); + if (!arg_collect.num) return str_printf(sym, "%c%c", open_char, close_char); for (i = 1; i < arg_collect.num; i++) { args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]); @@ -749,7 +757,7 @@ static const char* get_simple_type(char c) case 'N': type_string = "double"; break; case 'O': type_string = "long double"; break; case 'X': type_string = "void"; break; - case 'Z': type_string = "..."; break; +/* case 'Z': (...) variadic function arguments. Handled in get_args() */ default: type_string = NULL; break; } return type_string; @@ -800,7 +808,7 @@ static BOOL get_function_signature(struct parsed_symbol* sym, struct function_si if (!get_calling_convention(*sym->current++, &fs->call_conv, &fs->exported, sym->flags & ~UNDNAME_NO_ALLOCATION_LANGUAGE) || - !demangle_datatype(sym, &fs->return_ct, FALSE)) + !demangle_datatype(sym, &fs->return_ct, 0)) return FALSE;
if (!(fs->arguments = get_args(sym, TRUE, '(', ')')))
From: Eric Pouech epouech@codeweavers.com
Signesd-off-by: Eric Pouech epouech@codeweavers.com --- dlls/msvcrt/tests/cpp.c | 4 ++-- dlls/msvcrt/undname.c | 28 ++++++++++++++++++---------- 2 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c index bed1a5d4530..29bb126bcda 100644 --- a/dlls/msvcrt/tests/cpp.c +++ b/dlls/msvcrt/tests/cpp.c @@ -1177,7 +1177,7 @@ static void test_demangle(void) /* 23 */ {"??0streambuf@@QAE@ABV0@@Z", "public: __thiscall streambuf::streambuf(class streambuf const &)"}, /* 24 */ {"??0strstreambuf@@QAE@ABV0@@Z", "public: __thiscall strstreambuf::strstreambuf(class strstreambuf const &)"}, /* 25 */ {"??0strstreambuf@@QAE@H@Z", "public: __thiscall strstreambuf::strstreambuf(int)"}, -/* 26 */ {"??0strstreambuf@@QAE@P6APAXJ@ZP6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*)(long),void (__cdecl*)(void *))"}, +/* 26 */ {"??0strstreambuf@@QAE@Q6APAXJ@ZS6AXPAX@Z@Z", "public: __thiscall strstreambuf::strstreambuf(void * (__cdecl*const)(long),void (__cdecl*const volatile)(void *))"}, /* 27 */ {"??0strstreambuf@@QAE@PADH0@Z", "public: __thiscall strstreambuf::strstreambuf(char *,int,char *)"}, /* 28 */ {"??0strstreambuf@@QAE@PAEH0@Z", "public: __thiscall strstreambuf::strstreambuf(unsigned char *,int,unsigned char *)"}, /* 29 */ {"??0strstreambuf@@QAE@XZ", "public: __thiscall strstreambuf::strstreambuf(void)"}, @@ -1212,7 +1212,7 @@ static void test_demangle(void) /* 58 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAJ@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,long &)const "}, /* 59 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAK@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,unsigned long &)const "}, /* 60 */ {"?do_get@?$num_get@DV?$istreambuf_iterator@DU?$char_traits@D@std@@@std@@@std@@MBE?AV?$istreambuf_iterator@DU?$char_traits@D@std@@@2@V32@0AAVios_base@2@AAHAAM@Z", "protected: virtual class std::istreambuf_iterator<char,struct std::char_traits<char> > __thiscall std::num_get<char,class std::istreambuf_iterator<char,struct std::char_traits<char> > >::do_get(class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::istreambuf_iterator<char,struct std::char_traits<char> >,class std::ios_base &,int &,float &)const "}, -/* 61 */ {"?_query_new_handler@@YAP6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"}, +/* 61 */ {"?_query_new_handler@@YAR6AHI@ZXZ", "int (__cdecl*__cdecl _query_new_handler(void))(unsigned int)"}, /* 62 */ {"?register_callback@ios_base@std@@QAEXP6AXW4event@12@AAV12@H@ZH@Z", "public: void __thiscall std::ios_base::register_callback(void (__cdecl*)(enum std::ios_base::event,class std::ios_base &,int),int)"}, /* 63 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@JW4seekdir@ios_base@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(long,enum std::ios_base::seekdir)"}, /* 64 */ {"?seekg@?$basic_istream@DU?$char_traits@D@std@@@std@@QAEAAV12@V?$fpos@H@2@@Z", "public: class std::basic_istream<char,struct std::char_traits<char> > & __thiscall std::basic_istream<char,struct std::char_traits<char> >::seekg(class std::fpos<int>)"}, diff --git a/dlls/msvcrt/undname.c b/dlls/msvcrt/undname.c index 74856504685..923ec67d363 100644 --- a/dlls/msvcrt/undname.c +++ b/dlls/msvcrt/undname.c @@ -997,14 +997,22 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, case 'B': /* volatile reference */ if (!get_qualified_type(ct, sym, dt, flags)) goto done; break; + case 'P': /* Pointer */ case 'Q': /* const pointer */ case 'R': /* volatile pointer */ case 'S': /* const volatile pointer */ - if (!get_qualified_type(ct, sym, (flags & IN_ARGS) ? dt : 'P', flags)) goto done; - break; - case 'P': /* Pointer */ + if (!(flags & IN_ARGS)) dt = 'P'; if (isdigit(*sym->current)) - { + { + const char *ptr_qualif; + switch (dt) + { + default: + case 'P': ptr_qualif = NULL; break; + case 'Q': ptr_qualif = "const"; break; + case 'R': ptr_qualif = "volatile"; break; + case 'S': ptr_qualif = "const volatile"; break; + } /* FIXME: * P6 = Function pointer * P8 = Member function pointer @@ -1022,10 +1030,10 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, if (!get_function_qualifier(sym, &function_qualifier)) goto done; if (!get_function_signature(sym, &fs)) - goto done; + goto done;
- ct->left = str_printf(sym, "%s%s (%s %s::*", - fs.return_ct.left, fs.return_ct.right, fs.call_conv, class); + ct->left = str_printf(sym, "%s%s (%s %s::*%s", + fs.return_ct.left, fs.return_ct.right, fs.call_conv, class, ptr_qualif); ct->right = str_printf(sym, ")%s%s", fs.arguments, function_qualifier); } else if (*sym->current == '6') @@ -1037,14 +1045,14 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, if (!get_function_signature(sym, &fs)) goto done;
- ct->left = str_printf(sym, "%s%s (%s*", - fs.return_ct.left, fs.return_ct.right, fs.call_conv); + ct->left = str_printf(sym, "%s%s (%s*%s", + fs.return_ct.left, fs.return_ct.right, fs.call_conv, ptr_qualif); ct->flags = DT_NO_LEADING_WS; ct->right = str_printf(sym, ")%s", fs.arguments); } else goto done; } - else if (!get_qualified_type(ct, sym, 'P', flags)) goto done; + else if (!get_qualified_type(ct, sym, dt, flags)) goto done; break; case 'W': if (*sym->current == '4')
From: Eric Pouech epouech@codeweavers.com
Signed-off-by: Eric Pouech epouech@codeweavers.com --- tools/winedump/msmangle.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/tools/winedump/msmangle.c b/tools/winedump/msmangle.c index 2ac96a3fe5a..17954740cff 100644 --- a/tools/winedump/msmangle.c +++ b/tools/winedump/msmangle.c @@ -887,14 +887,22 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, case 'B': /* volatile reference */ if (!get_qualified_type(ct, sym, dt, flags)) goto done; break; + case 'P': /* Pointer */ case 'Q': /* const pointer */ case 'R': /* volatile pointer */ case 'S': /* const volatile pointer */ - if (!get_qualified_type(ct, sym, (flags & IN_ARGS) ? dt : 'P', flags)) goto done; - break; - case 'P': /* Pointer */ + if (!(flags & IN_ARGS)) dt = 'P'; if (isdigit(*sym->current)) - { + { + const char *ptr_qualif; + switch (dt) + { + default: + case 'P': ptr_qualif = NULL; break; + case 'Q': ptr_qualif = "const"; break; + case 'R': ptr_qualif = "volatile"; break; + case 'S': ptr_qualif = "const volatile"; break; + } /* FIXME: * P6 = Function pointer * P8 = Member function pointer @@ -912,10 +920,10 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, if (!get_function_qualifier(sym, &function_qualifier)) goto done; if (!get_function_signature(sym, &fs)) - goto done; + goto done;
- ct->left = str_printf(sym, "%s%s (%s %s::*", - fs.return_ct.left, fs.return_ct.right, fs.call_conv, class); + ct->left = str_printf(sym, "%s%s (%s %s::*%s", + fs.return_ct.left, fs.return_ct.right, fs.call_conv, class, ptr_qualif); ct->right = str_printf(sym, ")%s%s", fs.arguments, function_qualifier); } else if (*sym->current == '6') @@ -927,14 +935,14 @@ static BOOL demangle_datatype(struct parsed_symbol* sym, struct datatype_t* ct, if (!get_function_signature(sym, &fs)) goto done;
- ct->left = str_printf(sym, "%s%s (%s*", - fs.return_ct.left, fs.return_ct.right, fs.call_conv); + ct->left = str_printf(sym, "%s%s (%s*%s", + fs.return_ct.left, fs.return_ct.right, fs.call_conv, ptr_qualif); ct->flags = DT_NO_LEADING_WS; ct->right = str_printf(sym, ")%s", fs.arguments); } else goto done; } - else if (!get_qualified_type(ct, sym, 'P', flags)) goto done; + else if (!get_qualified_type(ct, sym, dt, flags)) goto done; break; case 'W': if (*sym->current == '4')
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=145654
Your paranoid android.
=== debian11b (64 bit WoW report) ===
winmm: mci: Timeout
This merge request was approved by Piotr Caban.
Did you consider changing `get_args` prototype to something like: `static char* get_args(struct parsed_symbol* sym, BOOL func)`? I think that `z_term` argument name is not very descriptive. `open_char` and `close_char` seems to be redundant.