diff: fixes for demangling
Fergus Henderson
fjh at cs.mu.oz.au
Thu Jul 24 06:06:09 AEST 1997
Hi,
Anyone want to review this change?
--
Ensure that all names are properly demangled, both by mdemangle
and in the profiler.
util/mdemangle.c:
Add code to demangle the special-case names properly.
tests/misc_tests/mdemangle_test.inp:
tests/misc_tests/mdemangle_test.exp:
Modify the expected output to reflect the bug fix to util/demangle.c.
profiler/demangle.m:
New module: contains a procedure for demangling Mercury labels.
profiler/demangle_test.m:
Test harness for demangle.m. Duplicates the functionality of
util/demangle.c. (Currently not used for anything except testing,
but we might one day want to use this code to replace util/demangle.c)
profiler/read.m:
Use the code in demangle.m to demangle labels.
Index: util/mdemangle.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/util/mdemangle.c,v
retrieving revision 1.18
diff -u -r1.18 mdemangle.c
--- mdemangle.c 1997/06/05 05:50:09 1.18
+++ mdemangle.c 1997/07/23 19:40:08
@@ -13,6 +13,12 @@
** A mercury symbol demangler.
** This is used to convert error messages from the linker back
** into a form that users can understand.
+**
+** This is implemented in C to minimize startup time and memory usage.
+**
+** BEWARE:
+** This code is duplicated in profiler/demangle.m and profiler/mdemangle.m.
+** Any changes here will need to be duplicated there and vice versa.
*/
#include <ctype.h>
@@ -25,6 +31,7 @@
static bool check_for_suffix(char *start, char *position, const char *suffix,
int sizeof_suffix, int *mode_num2);
static char *fix_mangled_ascii(char *str, char **end);
+static bool fix_mangled_special_case(char *str, char **end);
static bool cut_at_double_underscore(char **str, char *end);
static bool cut_trailing_integer(char *str, char **end, int *num);
static bool cut_trailing_underscore_integer(char *str, char **end, int *num);
@@ -73,10 +80,6 @@
/*
** demangle() - convert a mangled Mercury identifier into
** human-readable form and then print it to stdout
-**
-** Sorry, the following code is still fairly awful.
-** It ought to be rewritten in a language with
-** better string-handling facilities than C!
*/
static void
@@ -499,17 +502,13 @@
/*
** The compiler changes all names starting with `f_' so that
** they start with `f__' instead, and uses names starting with
- ** `f_' for mangled names which are sequences of decimal
+ ** `f_' for mangled names which are either descriptions (such
+ ** as `f_greater_than' for `>') or sequences of decimal
** reprententations of ASCII codes separated by underscores.
** If the name starts with `f__', we must change it back to
** start with `f_'. Otherwise, if it starts with `f_' we must
- ** convert the list of ASCII codes back into an identifier.
- **
- ** XXX Note: some symbols are special cased - eg `!' becomes
- ** `f_cut', we should probably translate these special cases
- ** back (see llds_out.m for the special cases). Presently, just
- ** the `f_' will be removed, which still leaves them quite
- ** readable.
+ ** convert the mnemonic or list of ASCII codes back into an
+ ** identifier.
*/
static char *
@@ -517,10 +516,30 @@
{
char *end = *real_end;
+ /*
+ ** If it starts with `f__', replace that with `f_'.
+ */
if (strncmp(str, "f__" , 3) == 0) {
str++;
*str = 'f';
- } else if (strncmp(str, "f_", 2) == 0) {
+ return str;
+ }
+
+ /*
+ ** If it starts with `f_' followed by a mnemonic description,
+ ** then replace that with its unmangled version
+ */
+ if (strncmp(str, "f_", 2) == 0 &&
+ fix_mangled_special_case(str, real_end))
+ {
+ return str;
+ }
+
+ /*
+ ** Otherwise, if it starts with `f_' we must convert the list of
+ ** ASCII codes back into an identifier.
+ */
+ if (strncmp(str, "f_", 2) == 0) {
char buf[1000];
char *num = str + 2;
int count = 0;
@@ -546,6 +565,59 @@
return str;
}
+static bool
+fix_mangled_special_case(char *str, char **real_end)
+{
+ static const struct {
+ const char *mangled_name;
+ const char *unmangled_name;
+ } translations[] = {
+ /*
+ ** Beware: we assume that the unmangled name is always
+ ** shorter than the mangled name.
+ */
+ { "f_not_equal", "\\=" },
+ { "f_greater_or_equal", ">=" },
+ { "f_less_or_equal", "=<" },
+ { "f_equal", "=" },
+ { "f_less_than", "<" },
+ { "f_greater_than", ">" },
+ { "f_plus", "+" },
+ { "f_times", "*" },
+ { "f_minus", "-" },
+ { "f_slash", "/" },
+ { "f_comma", "," },
+ { "f_semicolon", ";" },
+ { "f_cut", "!" }
+ };
+ const int num_translations =
+ sizeof(translations) / sizeof(translations[0]);
+
+ int i;
+
+ /*
+ ** check for the special cases listed in the table above.
+ */
+ for (i = 0; i < num_translations; i++) {
+ const char *mangled = translations[i].mangled_name;
+ size_t mangled_len = strlen(mangled);
+ if (strncmp(str, mangled, mangled_len) == 0) {
+ const char *unmangled = translations[i].unmangled_name;
+ size_t unmangled_len = strlen(unmangled);
+ size_t leftover_len = strlen(str) - mangled_len;
+
+ assert(unmangled_len <= mangled_len);
+
+ strcpy(str, unmangled);
+ memmove(str + unmangled_len, str + mangled_len,
+ leftover_len + 1);
+
+ *real_end = str + unmangled_len + leftover_len;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
static bool
check_for_suffix(char *start, char *position, const char *suffix,
Index: tests/misc_tests/mdemangle_test.inp
===================================================================
RCS file: /home/staff/zs/imp/tests/misc_tests/mdemangle_test.inp,v
retrieving revision 1.5
diff -u -r1.5 mdemangle_test.inp
--- mdemangle_test.inp 1997/06/05 05:50:16 1.5
+++ mdemangle_test.inp 1997/07/23 19:42:16
@@ -28,7 +28,7 @@
a mangled name
entry_mercury__f_cut_0_0
-<predicate 'cut'/0 mode 0>
+<predicate '!'/0 mode 0>
a compare predicate
entry_mercury____Compare___mercury_builtin__comparison_result_0_0
Index: tests/misc_tests/mdemangle_test.exp
===================================================================
RCS file: /home/staff/zs/imp/tests/misc_tests/mdemangle_test.exp,v
retrieving revision 1.5
diff -u -r1.5 mdemangle_test.exp
--- mdemangle_test.exp 1997/06/07 08:22:06 1.5
+++ mdemangle_test.exp 1997/07/23 19:41:07
@@ -27,8 +27,8 @@
<type layout for type 'float'/0>
a mangled name
-<predicate 'cut'/0 mode 0>
-<predicate 'cut'/0 mode 0>
+<predicate '!'/0 mode 0>
+<predicate '!'/0 mode 0>
a compare predicate
<compare/3 predicate for type 'mercury_builtin:comparison_result'/0>
Index: profiler/demangle.m
===================================================================
RCS file: demangle.m
diff -N demangle.m
--- /dev/null Thu Jul 24 06:02:47 1997
+++ demangle.m Thu Jul 24 06:00:25 1997
@@ -0,0 +1,496 @@
+%-----------------------------------------------------------------------------%
+%
+% Copyright (C) 1997 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%
+%-----------------------------------------------------------------------------%
+%
+% File: demangle.m
+% Author: fjh
+%
+% A mercury symbol demangler.
+% This is used to convert symbol names back
+% into a form that users can understand.
+%
+% BEWARE: the code here is duplicated in util/mdemangle.c,
+% so any changes here will need to be duplicated there.
+%
+%-----------------------------------------------------------------------------%
+
+:- module demangle.
+:- interface.
+:- import_module string.
+
+:- pred demangle(string::in, string::out) is det.
+
+/*---------------------------------------------------------------------------*/
+
+:- implementation.
+:- import_module int, list, char, std_util, bool, require.
+
+:- type pred_category ---> index ; unify ; compare ; ordinary.
+:- type data_category ---> common ; info ; layout ; functors.
+
+demangle(MangledName, Name) :-
+ ( demangle_from_asm(MangledName, DemangledName) ->
+ Name = DemangledName
+ ;
+ Name = MangledName
+ ).
+
+:- pred demangle_from_asm(string, string).
+:- mode demangle_from_asm(in, out) is semidet.
+demangle_from_asm -->
+ % skip any leading underscore inserted by the C compiler
+ maybe_remove_prefix("_"),
+
+ % skip the `entry_' prefix, if any
+ maybe_remove_prefix("entry_"),
+
+ demangle_from_c.
+
+:- pred demangle_from_c(string, string).
+:- mode demangle_from_c(in, out) is semidet.
+demangle_from_c -->
+ ( demangle_proc ->
+ { true }
+ ; demangle_data ->
+ { true }
+ ;
+ { fail }
+ ).
+
+/*---------------------------------------------------------------------------*/
+
+:- pred demangle_proc(string, string).
+:- mode demangle_proc(in, out) is semidet.
+demangle_proc -->
+ remove_prefix("mercury__"),
+
+ %
+ % strip off the `fn__' prefix, if any
+ %
+ ( remove_prefix("fn__") ->
+ { PredOrFunc = "function" }
+ ;
+ { PredOrFunc = "predicate" }
+ ),
+
+ %
+ % Get integer from end of string (it might be the mode number,
+ % it might be the internal label number).
+ %
+ remove_trailing_int(Int),
+
+ ( m_remove_suffix("i") ->
+ %
+ % if we got to an `i', that means it is an internal
+ % label of the form `mercury__append_3_0_i1'
+ % in that case, save the internal label number and then
+ % get the mode number
+ %
+ { MaybeInternalLabelNum = yes(Int) },
+ m_remove_suffix("_"),
+ remove_trailing_int(ModeNum)
+ ;
+ { MaybeInternalLabelNum = no },
+ { ModeNum = Int }
+ ),
+
+ %
+ % scan back past the arity number and then parse it
+ %
+ m_remove_suffix("_"),
+ remove_trailing_int(Arity),
+ m_remove_suffix("_"),
+
+ %
+ % Now start processing from the start of the string again.
+ % Check whether the start of the string matches the name of
+ % one of the special compiler-generated predicates; if so,
+ % set the `category' to the appropriate value and then
+ % skip past the prefix.
+ %
+ ( remove_prefix("__Unify__") ->
+ { Category = unify }
+ ; remove_prefix("__Compare__") ->
+ { Category = compare },
+ { ModeNum = 0 } % sanity check
+ ; remove_prefix("__Index__") ->
+ { Category = index },
+ { ModeNum = 0 } % sanity check
+ ;
+ { Category = ordinary }
+ ),
+
+ %
+ % Fix any ascii codes mangled in the predicate name
+ %
+ fix_mangled_ascii,
+
+ %
+ % Process the mangling introduced by unused_args.m.
+ % This involves stripping off the `__ua<m>' or `__uab<m>' added to
+ % the end of the predicate/function name, where m is the mode number.
+ %
+ (
+ remove_trailing_int(_UA_ModeNum),
+ m_remove_suffix("__ua")
+ ->
+ { UnusedArgs = yes }
+ ;
+ remove_trailing_int(_UA_ModeNum),
+ m_remove_suffix("__uab")
+ ->
+ { UnusedArgs = yes }
+ ;
+ { UnusedArgs = no }
+ ),
+
+ %
+ % Process the mangling introduced by higher_order.m.
+ % This involves stripping off the `__ho<n>' where
+ % n is a unique identifier for this specialized version
+ %
+ (
+ remove_trailing_int(_HO_ModeNum),
+ m_remove_suffix("__ho")
+ ->
+ { HigherOrder = yes }
+ ;
+ { HigherOrder = no }
+ ),
+
+ %
+ % Separate the module name from the type name for the compiler
+ % generated predicates.
+ %
+ ( { Category \= ordinary } ->
+ remove_prefix("_"),
+ remove_maybe_module_prefix(MaybeModule),
+ { MaybeModule \= yes("") }
+ ;
+ { MaybeModule = no }
+ ),
+
+ %
+ % Make sure special predicates with unused_args
+ % are reported correctly.
+ %
+
+ ( { UnusedArgs = yes, Category \= ordinary } ->
+ remove_trailing_int(Arity)
+ ;
+ { true }
+ ),
+
+ %
+ % Now, finally, we can construct the demangled symbol name
+ %
+ =(PredName),
+ { format_proc(Category, MaybeModule, PredOrFunc, PredName,
+ Arity, ModeNum, HigherOrder, UnusedArgs, MaybeInternalLabelNum,
+ Parts, []) },
+ { string__append_list(Parts, DemangledName) },
+ dcg_set(DemangledName).
+
+:- pred format_proc(pred_category, maybe(string), string, string, int, int,
+ bool, bool, maybe(int), list(string), list(string)).
+:- mode format_proc(in, in, in, in, in, in, in, in, in, out, in) is det.
+format_proc(Category, MaybeModule, PredOrFunc, PredName, Arity, ModeNum,
+ HigherOrder, UnusedArgs, MaybeInternalLabelNum) -->
+ ["<"],
+ {
+ Category = unify,
+ get_maybe(MaybeModule, Module),
+ string__format("unification predicate for type '%s:%s'/%d mode %d",
+ [s(Module), s(PredName), i(Arity), i(ModeNum)],
+ MainPart)
+ ;
+ Category = compare,
+ get_maybe(MaybeModule, Module),
+ string__format("compare/3 predicate for type '%s:%s'/%d",
+ [s(Module), s(PredName), i(Arity)],
+ MainPart)
+ ;
+ Category = index,
+ get_maybe(MaybeModule, Module),
+ string__format("index/2 predicate for type '%s:%s'/%d",
+ [s(Module), s(PredName), i(Arity)],
+ MainPart)
+ ;
+ Category = ordinary,
+ string__format("%s '%s'/%d mode %d",
+ [s(PredOrFunc), s(PredName), i(Arity), i(ModeNum)],
+ MainPart)
+ },
+ [MainPart],
+ ( { HigherOrder = yes } ->
+ [" (specialized)"]
+ ;
+ []
+ ),
+ ( { UnusedArgs = yes } ->
+ [" (minus unused args)"]
+ ;
+ []
+ ),
+ ( { MaybeInternalLabelNum = yes(Internal) } ->
+ { string__format(" label %d", [i(Internal)], Label) },
+ [Label]
+ ;
+ []
+ ),
+ [">"].
+
+/*---------------------------------------------------------------------------*/
+
+%
+% Code to deal with mercury_data items.
+%
+
+:- pred demangle_data(string, string).
+:- mode demangle_data(in, out) is semidet.
+demangle_data -->
+ remove_prefix("mercury_data_"),
+ remove_maybe_module_prefix(MaybeModule0),
+ { MaybeModule0 = yes("") ->
+ MaybeModule = no
+ ;
+ MaybeModule = MaybeModule0
+ },
+ ( remove_prefix("base_type_info_") ->
+ { DataCategory = info },
+ remove_trailing_int(Arity),
+ m_remove_suffix("_")
+ ; remove_prefix("base_type_layout_") ->
+ { DataCategory = layout },
+ remove_trailing_int(Arity),
+ m_remove_suffix("_")
+ ; remove_prefix("base_type_functors_") ->
+ { DataCategory = functors },
+ remove_trailing_int(Arity),
+ m_remove_suffix("_")
+ ; remove_prefix("common_") ->
+ { DataCategory = common },
+ remove_trailing_int(Arity)
+ ;
+ { fail }
+ ),
+
+ fix_mangled_ascii,
+
+ =(Name),
+ { format_data(DataCategory, MaybeModule, Name, Arity, Result) },
+ dcg_set(Result).
+
+:- pred format_data(data_category, maybe(string), string, int, string).
+:- mode format_data(in, in, in, in, out) is semidet.
+format_data(info, MaybeModule, Name, Arity, Result) :-
+ ( MaybeModule = yes(Module) ->
+ string__format("<base type_info for type '%s:%s'/%d>",
+ [s(Module), s(Name), i(Arity)], Result)
+ ;
+ string__format("<base type_info for type '%s'/%d>",
+ [s(Name), i(Arity)], Result)
+ ).
+format_data(layout, MaybeModule, Name, Arity, Result) :-
+ ( MaybeModule = yes(Module) ->
+ string__format("<type layout for type '%s:%s'/%d>",
+ [s(Module), s(Name), i(Arity)], Result)
+ ;
+ string__format("<type layout for type '%s'/%d>",
+ [s(Name), i(Arity)], Result)
+ ).
+format_data(functors, MaybeModule, Name, Arity, Result) :-
+ ( MaybeModule = yes(Module) ->
+ string__format("<type functors for type '%s:%s'/%d>",
+ [s(Module), s(Name), i(Arity)], Result)
+ ;
+ string__format("<type functors for type '%s'/%d>",
+ [s(Name), i(Arity)], Result)
+ ).
+format_data(common, MaybeModule, _Name, Arity, Result) :-
+ ( MaybeModule = yes(Module) ->
+ string__format("<shared constant number %d for module %s>",
+ [i(Arity), s(Module)], Result)
+ ;
+ fail
+ ).
+
+/*---------------------------------------------------------------------------*/
+
+ %
+ % The compiler changes all names starting with `f_' so that
+ % they start with `f__' instead, and uses names starting with
+ % `f_' for mangled names which are either descriptions (such
+ % as `f_greater_than' for `>') or sequences of decimal
+ % reprententations of ASCII codes separated by underscores.
+ % If the name starts with `f__', we must change it back to
+ % start with `f_'. Otherwise, if it starts with `f_' we must
+ % convert the mnemonic or list of ASCII codes back into an
+ % identifier.
+ %
+
+:- pred fix_mangled_ascii(string, string).
+:- mode fix_mangled_ascii(in, out) is semidet.
+fix_mangled_ascii -->
+ ( remove_prefix("f__") ->
+ insert_prefix("f_")
+ ; remove_prefix("f_not_equal") ->
+ insert_prefix("\\=")
+ ; remove_prefix("f_greater_or_equal") ->
+ insert_prefix(">=")
+ ; remove_prefix("f_less_or_equal") ->
+ insert_prefix("=<")
+ ; remove_prefix("f_equal") ->
+ insert_prefix("=")
+ ; remove_prefix("f_less_than") ->
+ insert_prefix("<")
+ ; remove_prefix("f_greater_than") ->
+ insert_prefix(">")
+ ; remove_prefix("f_minus") ->
+ insert_prefix("-")
+ ; remove_prefix("f_plus") ->
+ insert_prefix("+")
+ ; remove_prefix("f_times") ->
+ insert_prefix("*")
+ ; remove_prefix("f_slash") ->
+ insert_prefix("/")
+ ; remove_prefix("f_comma") ->
+ insert_prefix(",")
+ ; remove_prefix("f_semicolon") ->
+ insert_prefix(";")
+ ; remove_prefix("f_cut") ->
+ insert_prefix("!")
+ ; remove_prefix("f_") ->
+ fix_mangled_ascii_chars
+ ;
+ []
+ ).
+
+:- pred fix_mangled_ascii_chars(string, string).
+:- mode fix_mangled_ascii_chars(in, out) is semidet.
+fix_mangled_ascii_chars -->
+ remove_int(I),
+ ( remove_prefix("_") ->
+ fix_mangled_ascii_chars
+ ;
+ []
+ ),
+ { char__to_int(C, I) },
+ insert_prefix_char(C).
+
+/*---------------------------------------------------------------------------*/
+
+:- pred remove_int(int, string, string).
+:- mode remove_int(out, in, out) is semidet.
+remove_int(Int) -->
+ remove_digit(Digit),
+ remove_int_2(Digit, Int).
+
+:- pred remove_int_2(int, int, string, string).
+:- mode remove_int_2(in, out, in, out) is semidet.
+remove_int_2(Int0, Int) -->
+ ( remove_digit(Next) ->
+ { Int1 is Int0 * 10 + Next },
+ remove_int_2(Int1, Int)
+ ;
+ { Int = Int0 }
+ ).
+
+:- pred remove_digit(int, string, string).
+:- mode remove_digit(out, in, out) is semidet.
+remove_digit(Digit, String0, String) :-
+ string__first_char(String0, Char, String),
+ digit(Char, Digit).
+
+:- pred digit(character, int).
+:- mode digit(in, uo) is semidet.
+digit('0', 0).
+digit('1', 1).
+digit('2', 2).
+digit('3', 3).
+digit('4', 4).
+digit('5', 5).
+digit('6', 6).
+digit('7', 7).
+digit('8', 8).
+digit('9', 9).
+
+/*---------------------------------------------------------------------------*/
+
+:- pred remove_maybe_module_prefix(maybe(string), string, string).
+:- mode remove_maybe_module_prefix(out, in, out) is det.
+remove_maybe_module_prefix(MaybeModule, String0, String) :-
+ ( string__sub_string_search(String0, "__", Index) ->
+ string__left(String0, Index, Module),
+ string__length(String0, Len),
+ Index2 is Index + 2,
+ string__substring(String0, Index2, Len, String),
+ MaybeModule = yes(Module)
+ ;
+ String = String0,
+ MaybeModule = no
+ ).
+
+:- pred maybe_remove_prefix(string, string, string).
+:- mode maybe_remove_prefix(in, in, out) is det.
+maybe_remove_prefix(Prefix) -->
+ ( remove_prefix(Prefix) -> [] ; [] ).
+
+:- pred remove_prefix(string, string, string).
+:- mode remove_prefix(in, in, out) is semidet.
+remove_prefix(Prefix, Name0, Name) :-
+ string__append(Prefix, Name, Name0).
+
+:- pred m_remove_suffix(string, string, string).
+:- mode m_remove_suffix(in, in, out) is semidet.
+m_remove_suffix(Suffix, Name0, Name) :-
+ string__remove_suffix(Name0, Suffix, Name).
+
+:- pred insert_prefix(string, string, string).
+:- mode insert_prefix(in, in, out) is det.
+insert_prefix(Prefix, Name0, Name) :-
+ string__append(Prefix, Name0, Name).
+
+:- pred insert_prefix_char(char, string, string).
+:- mode insert_prefix_char(in, in, out) is det.
+insert_prefix_char(Prefix, Name0, Name) :-
+ string__first_char(Name, Prefix, Name0).
+
+:- pred dcg_set(T1, T2, T1).
+:- mode dcg_set(in, in, out) is det.
+dcg_set(X, _, X).
+
+:- pred get_maybe((std_util:maybe(T)), T).
+:- mode get_maybe(in, out) is det.
+get_maybe(no, _) :- error("get_maybe").
+get_maybe(yes(X), X).
+
+:- pred remove_trailing_int(int, string, string).
+:- mode remove_trailing_int(out, in, out) is semidet.
+remove_trailing_int(Int) -->
+ remove_trailing_digit(Digit),
+ ( remove_trailing_int(Rest) ->
+ { Int is Rest * 10 + Digit }
+ ;
+ { Int = Digit }
+ ).
+
+:- pred remove_trailing_digit(int, string, string).
+:- mode remove_trailing_digit(out, in, out) is semidet.
+remove_trailing_digit(Digit, String0, String) :-
+ string_last_char(String0, Char, String),
+ digit(Char, Digit).
+
+:- pred string_last_char(string, character, string).
+:- mode string_last_char(in, out, out) is semidet.
+string_last_char(String0, Char, String) :-
+ string__length(String0, Len),
+ Len1 is Len - 1,
+ string__index(String0, Len1, Char),
+ string__left(String0, Len1, String).
+
+/*---------------------------------------------------------------------------*/
Index: profiler/demangle_test.m
===================================================================
RCS file: demangle_test.m
diff -N demangle_test.m
--- /dev/null Thu Jul 24 06:02:47 1997
+++ demangle_test.m Thu Jul 24 05:55:40 1997
@@ -0,0 +1,76 @@
+%-----------------------------------------------------------------------------%
+%
+% Copyright (C) 1997 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%
+%-----------------------------------------------------------------------------%
+%
+% File: mdemangle.m
+% Author: fjh
+%
+% Front-end to a mercury symbol demangler.
+% This is used to convert error messages from the linker back
+% into a form that users can understand.
+%
+% BEWARE:
+% The code here duplicates the functionality of util/mdemangle.c.
+% Any changes here will require corresponding changes there.
+%
+% We might eventually replace util/mdemangle.c with this Mercury version.
+%
+%-----------------------------------------------------------------------------%
+
+:- module mdemangle.
+:- interface.
+
+:- import_module io.
+:- pred main(state::di, state::uo) is det.
+
+:- implementation.
+:- import_module demangle.
+:- import_module list, char, string.
+
+main -->
+ io__command_line_arguments(Args),
+ ( { Args \= [] } ->
+ %
+ % invoke demangle/2 on each command line argument
+ %
+ { list__map(demangle, Args, DemangledArgs) },
+ io__write_list(DemangledArgs, "\n", io__write_string), io__nl
+ ;
+ %
+ % copy stdin to stdout, calling demangle/2 for
+ % every valid C identifier in the input
+ %
+ demangle_stdin([])
+ ).
+
+:- pred demangle_stdin(list(char)::in, state::di, state::uo) is det.
+demangle_stdin(RevChars) -->
+ io__read_char(Result),
+ ( { Result = ok(Char) },
+ ( { char__is_alnum_or_underscore(Char) } ->
+ demangle_stdin([Char | RevChars])
+ ;
+ { string__from_rev_char_list(RevChars, MangledName) },
+ { demangle(MangledName, DemangledName) },
+ io__write_string(DemangledName),
+ io__write_char(Char),
+ demangle_stdin([])
+ )
+ ; { Result = eof },
+ { string__from_rev_char_list(RevChars, MangledName) },
+ { demangle(MangledName, DemangledName) },
+ io__write_string(DemangledName)
+ ; { Result = error(Error) },
+ { io__error_message(Error, Message) },
+ io__input_stream_name(StreamName),
+ io__progname("mdemangle", ProgName),
+ io__write_strings([ProgName, ": ",
+ "error reading input file `", StreamName, "': \n\t",
+ Message, "\n"])
+ ).
+
+%-----------------------------------------------------------------------------%
Index: profiler/read.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/profiler/read.m,v
retrieving revision 1.5
diff -u -r1.5 read.m
--- read.m 1997/07/01 04:12:01 1.5
+++ read.m 1997/07/23 18:50:25
@@ -85,8 +85,8 @@
io__read_word(WordResult),
(
{ WordResult = ok(CharList0) },
- { label_demangle(CharList0, CharList) },
- { string__from_char_list(CharList, LabelName) },
+ { string__from_char_list(CharList0, LabelName0) },
+ { demangle(LabelName0, LabelName) },
{ MaybeLabelName = yes(LabelName) }
;
{ WordResult = eof },
@@ -137,8 +137,8 @@
io__read_word(WordResult),
(
{ WordResult = ok(CharList0) },
- { label_demangle(CharList0, CharList) },
- { string__from_char_list(CharList, LabelName) }
+ { string__from_char_list(CharList0, LabelName0) },
+ { demangle(LabelName0, LabelName) },
;
{ WordResult = eof },
{ error("read_label_name: EOF reached") }
@@ -177,39 +177,3 @@
).
%-----------------------------------------------------------------------------%
-
-:- pred label_demangle(list(char), list(char)).
-:- mode label_demangle(in, out) is det.
-
-label_demangle(CharList0, CharList) :-
- (
- CharList0 = ['m','e','r','c','u','r','y','_','_' | CharList1]
- ->
- demangle_arity_and_mode(CharList1, CharList)
- ;
- CharList = CharList0
- ).
-
-
-:- pred demangle_arity_and_mode(list(char), list(char)).
-:- mode demangle_arity_and_mode(in, out) is det.
-
-demangle_arity_and_mode(CharList0, CharList) :-
- list__reverse(CharList0, CharList1),
- CharList2 = [')' | CharList1],
- read__replace(CharList2, '_', '(', CharList3),
- read__replace(CharList3, '_', '/', CharList4),
- list__reverse(CharList4, CharList).
-
-
-:- pred read__replace(list(char), char, char, list(char)).
-:- mode read__replace(in, in, in, out) is det.
-
-read__replace(L0, D, R, L) :-
- (
- list__replace_first(L0, D, R, L1)
- ->
- L = L1
- ;
- error("demangle_label: ill formed label\n")
- ).
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list