OSDN Git Service

2003-02-27 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / demangle.cc
1 // C++ IA64 / g++ v3 demangler  -*- C++ -*-
2
3 // Copyright (C) 2003 Free Software Foundation, Inc.
4 // Written by Carlo Wood <carlo@alinoe.com>
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING.  If not, write to the Free
19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 // USA.
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 #include <cxxabi.h>
32 #include "demangle.h"
33
34 // __cxa_demangle
35 //
36 // Demangle a C++ symbol or type name.
37 //
38 // `mangled-name' is a pointer to a null-terminated array of characters.
39 // It may be either an external name, i.e. with a "_Z" prefix, or an
40 // internal NTBS mangling, e.g. of a type for type_info.
41 //
42 // `buf' may be null.  If it is non-null, then n must also be non-null,
43 // and buf is a pointer to an array, of at least *n characters, that
44 // was allocated using malloc.
45 //
46 // `status' points to an int that is used as an error indicator. It is
47 // permitted to be null, in which case the user just doesn't get any
48 // detailed error information. 
49 //
50 // Returns: a pointer to a null-terminated array of characters, the
51 //          demangled name.  Or NULL in case of failure.
52 //
53 // If there is an error in demangling, the return value is a null pointer.
54 // The user can examine *status to find out what kind of error occurred.
55 // Meaning of error indications:
56 //
57 //     *  0: success
58 //     * -1: memory allocation failure
59 //     * -2: invalid mangled name
60 //     * -3: invalid arguments (e.g. buf nonnull and n null) 
61 //
62
63 namespace __cxxabiv1 
64 {
65   namespace 
66   {
67     char* const error = 0;
68
69     enum status_codes 
70     {
71       success = 0,
72       memory_allocation_failure = -1,
73       invalid_mangled_name = -2,
74       invalid_argument = -3
75     };
76
77     inline char*
78     failure(status_codes error_code, int* status)
79     {
80       if (status)
81         *status = error_code;
82       return error;
83     }
84
85     char*
86     finish(char const* demangled_name, size_t demangled_name_size,
87            char* buf, size_t* n, int* status)
88     {
89       if (!buf || *n < demangled_name_size + 1)
90       {
91         if (n)
92           *n = demangled_name_size + 1;
93         buf = (char*)realloc(buf, demangled_name_size + 1);
94         if (!buf)
95           return failure(memory_allocation_failure, status);
96       }
97       if (status)
98         *status = success;
99       std::strncpy(buf, demangled_name, demangled_name_size);
100       buf[demangled_name_size] = 0;
101       return buf;
102     }
103   } // namespace
104
105   char*
106   __cxa_demangle(char const* mangled_name, char* buf, std::size_t* n, 
107                  int* status)
108   {
109     using namespace __gnu_cxx;
110     typedef demangler::session<std::allocator<char> > session_type;
111
112     if (!mangled_name || (buf && !n))
113       return failure(invalid_argument, status);
114
115     std::string result;
116     if (mangled_name[0] == '_')         
117     {
118       // External name?
119       if (mangled_name[1] == 'Z')               
120       {
121         // C++ name?
122         int cnt = session_type::
123             decode_encoding(result, mangled_name + 2, INT_MAX);
124         if (cnt < 0 || mangled_name[cnt + 2] != 0)
125           return failure(invalid_mangled_name, status);
126         return finish(result.data(), result.size(), buf, n, status);
127       }
128       else if (mangled_name[1] == 'G')  
129       {
130         // Possible _GLOBAL__ extension?
131         if (!std::strncmp(mangled_name, "_GLOBAL__", 9) 
132             && (mangled_name[9] == 'D' || mangled_name[9] == 'I')
133             && mangled_name[10] == '_' && mangled_name[11] == '_' 
134             && mangled_name[12] == 'Z')
135         {
136           if (mangled_name[9] == 'D')
137             result.assign("global destructors keyed to ", 28);
138           else
139             result.assign("global constructors keyed to ", 29);
140           int cnt = session_type::
141               decode_encoding(result, mangled_name + 13, INT_MAX);
142           if (cnt < 0 || mangled_name[cnt + 13] != 0)
143             return failure(invalid_mangled_name, status);
144           return finish(result.data(), result.size(), buf, n, status);
145         }
146       }
147     }
148
149     // Ambiguities are possible between extern "C" object names and
150     // internal built-in type names, e.g. "i" may be either an object
151     // named "i" or the built-in "int" type.  Such ambiguities should
152     // be resolved to user names over built-in names.  Builtin types
153     // are any single lower case character.  Any other single
154     // character is not a mangled type so we can treat those the same
155     // here.
156     if (mangled_name[1] == 0)
157       return finish(mangled_name, 1, buf, n, status);
158
159     // Not a built-in type or external name, try to demangle input as
160     // NTBS mangled type name.
161     session_type demangler_session(mangled_name, INT_MAX);
162     if (!demangler_session.decode_type(result) 
163         || demangler_session.remaining_input_characters())
164     {
165       // Failure to demangle, assume extern "C" name.
166       result = mangled_name;            
167     }
168     return finish(result.data(), result.size(), buf, n, status);
169   }
170 } // namespace __cxxabiv1