File: Synopsis/PTree/Encoding.hh
  1//
  2// Copyright (C) 1997 Shigeru Chiba
  3// Copyright (C) 2004 Stefan Seefeld
  4// All rights reserved.
  5// Licensed to the public under the terms of the GNU LGPL (>= 2),
  6// see the file COPYING for details.
  7//
  8#ifndef Synopsis_PTree_Encoding_hh_
  9#define Synopsis_PTree_Encoding_hh_
 10
 11#include <string>
 12#include <iostream>
 13#include <cassert>
 14#include <cstring>
 15#include <cstdio> // for EOF
 16
 17namespace Synopsis
 18{
 19namespace PTree
 20{
 21
 22class Node;
 23class Atom;
 24
 25//. An Encoding represents a mangled (type) name. Here is a quick reference of the grammar:
 26//.
 27//. - `b`: boolean
 28//. - `c`: char
 29//. - `w`: wchar_t
 30//. - `i`: int (signed, unsigned)
 31//. - `s`: short (short int)
 32//. - `l`: long (long int)
 33//. - `j`: long long
 34//. - `f`: float
 35//. - `d`: double
 36//. - `r`: long double
 37//. - `v`: void
 38//. - `T`: template class (e.g. `Foo<int,char>` ==> `T[3]Foo[2]ic`.  `[2]` means
 39//.   the length of `ic`.  It doesn't mean the number of template arguments.
 40//.
 41//. - `e`: ...
 42//. - `?`: no return type.  the return type of constructors
 43//. - `*`: non-type template parameter
 44//.
 45//. - `S`: `signed`
 46//. - `U`: `unsigned`
 47//. - `C`: `const`
 48//. - `V`: `volatile`
 49//.
 50//. - `P`: pointer
 51//. - `R`: reference
 52//. - `A`: array (e.g. `char[16]` ==> `A16_c`)
 53//. - `F`: function (e.g. `char foo(int)` ==> `Fi_c`)
 54//. - `M`: pointer to member (e.g. `Type::*` ==> `M[4]Type`)
 55//.
 56//. - `Q`: qualified class (e.g. `X::YY` ==> `Q[2][1]X[2]YY`, `::YY` ==> `Q[2][0][2]YY`)
 57//.
 58//. - `[x]`: means `0x80 + x`
 59//. - `0`: means `::` (global scope)
 60//.
 61//. Special function names:
 62//.
 63//. - operator + ==> +
 64//. - operator new[] ==> new[]
 65//. - operator <type> ==> @<encoded type>		cast operator
 66//.
 67class Encoding 
 68{
 69public:
 70  struct char_traits
 71  {
 72    typedef unsigned char  char_type;
 73    typedef unsigned long  int_type;
 74    typedef std::streampos pos_type;
 75    typedef std::streamoff off_type;
 76    typedef std::mbstate_t state_type;
 77
 78    static void assign(char_type &c1, const char_type &c2) { c1 = c2;}
 79    static bool eq(const char_type &c1, const char_type &c2) { return c1 == c2;}
 80    static bool lt(const char_type &c1, const char_type &c2) { return c1 < c2;}
 81    static int compare(const char_type *s1, const char_type *s2, std::size_t n) { return memcmp(s1, s2, n);}
 82    static std::size_t length(const char_type *s) { return strlen((const char *)s);}
 83    static const char_type *find(const char_type *s, std::size_t n, const char_type &a)
 84    { return static_cast<const char_type *>(memchr(s, a, n));}
 85    static char_type *move(char_type *s1, const char_type *s2, std::size_t n)
 86    { return static_cast<char_type *>(memmove(s1, s2, n));}
 87    static char_type *copy(char_type *s1, const char_type *s2, std::size_t n)
 88    { return static_cast<char_type *>(memcpy(s1, s2, n));}
 89    static char_type *assign(char_type *s, std::size_t n, char_type a)
 90    { return static_cast<char_type *>(memset(s, a, n));}
 91    static char_type to_char_type(const int_type &c) { return static_cast<char_type>(c);}
 92    static int_type to_int_type(const char_type &c) { return static_cast<int_type>(c);}
 93    static bool eq_int_type(const int_type &c1, const int_type &c2) { return c1 == c2;}
 94    static int_type eof() { return static_cast<int_type>(EOF);}
 95    static int_type not_eof(const int_type &c) { return !eq_int_type(c, eof()) ? c : to_int_type(char_type());}
 96  };
 97
 98  typedef std::basic_string<unsigned char, char_traits> Code;
 99  typedef Code::const_iterator iterator;
100
101  static void do_init_static();
102
103  Encoding() {}
104  Encoding(const Code &b) : my_buffer(b) {}
105  Encoding(const char *b) : my_buffer(b, b + strlen(b)) {}
106  Encoding(const char *b, size_t s) : my_buffer(b, b + s) {}
107  Encoding(iterator b, iterator e) : my_buffer(b, e) {}
108  static Encoding simple_name(PTree::Atom const *name);
109
110  void clear() { my_buffer.clear();}
111  bool empty() const { return my_buffer.empty();}
112  size_t size() const { return my_buffer.size();}
113  iterator begin() const { return my_buffer.begin();}
114  iterator end() const { return my_buffer.end();}
115  unsigned char front() const { return *begin();}
116  unsigned char at(size_t i) const { return my_buffer.at(i);}
117  //. return a copy of the underlaying buffer
118  //. FIXME: this is a temporary workaround while there are
119  //. still places that use raw strings
120  const char *copy() const;
121
122  bool operator == (const Encoding &e) const { return my_buffer == e.my_buffer;}
123  bool operator == (const std::string &s) const { return my_buffer == (const unsigned char *)s.c_str();}
124  bool operator == (const char *s) const { return my_buffer == (const unsigned char *)s;}
125
126  void prepend(unsigned char c) { my_buffer.insert(my_buffer.begin(), c);}
127  void prepend(const char *p, size_t s) { my_buffer.insert(0, (const unsigned char *)p, s);}
128  void prepend(const Encoding &e) { my_buffer.insert(0, e.my_buffer);}
129
130  void append(unsigned char c) { my_buffer.append(1, c);}
131  void append(const char *p, size_t s) { my_buffer.append((const unsigned char *)p, s);}
132  void append(const Encoding &e) { my_buffer.append(e.my_buffer);}
133  void append_with_length(const char *s, size_t n) { append(0x80 + n); append((const char *)s, n);}
134  void append_with_length(const Encoding &e) { append(0x80 + e.size()); append(e);}
135
136  unsigned char pop();
137  void pop(size_t n) { my_buffer.erase(my_buffer.begin(), my_buffer.begin() + n);}
138
139  void cv_qualify(const Node *, const Node * = 0);
140  void simple_const() { append("Ci", 2);}
141  void global_scope();
142  void simple_name(const Node *);
143  void anonymous();
144  void template_(const Node *, const Encoding &);
145  void qualified(int);
146  void destructor(const Node *);
147  void ptr_operator(int);
148  void ptr_to_member(const Encoding &, int);
149  void cast_operator(const Encoding &);
150  void array() { prepend("A_", 2);}
151  void array(unsigned long s);
152  void function(const Encoding &e) { prepend(e);}
153  void recursion(const Encoding &e) { prepend(e);}
154  void start_func_args() { append('F');}
155  void end_func_args() { append('_');}
156  void void_() { append('v');}
157  void ellipsis_arg() { append('e');}
158  void no_return_type() { append('?');}
159  void value_temp_param() { append('*');}
160
161  //. if this Encoding represents a qualified name,
162  //. return the name of the outer scope
163  Encoding get_scope() const;
164  //. if this Encoding represents a qualified name,
165  //. return the name of the symbol inside the outer scope,
166  //. else return the unmodified name
167  Encoding get_symbol() const;
168  Encoding get_template_arguments() const;
169  
170  std::string unmangled() const;
171
172  PTree::Node *make_name();
173  PTree::Node *make_qname();
174  PTree::Node *make_ptree(PTree::Node *);
175  bool is_simple_name() const { return front() >= 0x80;}
176  bool is_global_scope() const { return front() == 0x80 && size() == 1;}
177  bool is_qualified() const { return front() == 'Q';}
178  bool is_function() const;
179  bool is_template() const { return front() == 'T';}
180  PTree::Node *name_to_ptree();
181
182  friend bool operator < (const Encoding &, const Encoding &);
183  friend std::ostream &operator << (std::ostream &, const Encoding &);
184
185private:
186
187  iterator end_of_scope() const;
188
189  Code my_buffer;
190
191public:
192  static PTree::Node *bool_t, *char_t, *wchar_t_t, *int_t, *short_t, *long_t,
193		 *float_t, *double_t, *void_t;
194
195  static PTree::Node *signed_t, *unsigned_t, *const_t, *volatile_t;
196
197  static PTree::Node *operator_name, *new_operator, *anew_operator,
198		 *delete_operator, *adelete_operator;
199
200  static PTree::Node *star, *ampersand, *comma, *dots, *scope, *tilder,
201		 *left_paren, *right_paren, *left_bracket, *right_bracket,
202		 *left_angle, *right_angle;
203};
204
205inline bool operator < (const Encoding &e1, const Encoding &e2) 
206{
207  return e1.my_buffer < e2.my_buffer;
208}
209
210inline std::ostream &operator << (std::ostream &os, const Encoding &e)
211{
212  for (Encoding::iterator i = e.begin();
213       i != e.end();
214       ++i)
215    if(*i < 0x80) os.put(static_cast<char>(*i));
216    else os << '[' << static_cast<int>(*i - 0x80) << ']';
217  return os;
218}
219
220inline unsigned char Encoding::pop() 
221{
222  unsigned char code = my_buffer[0]; 
223  my_buffer.erase(0, 1); 
224  return code;
225}
226
227inline bool Encoding::is_function() const 
228{
229  if (front() == 'F') return true;
230  // const (member) function.
231  else if (front() == 'C' && *(begin() + 1) == 'F') return true;
232  else return false;
233}
234
235}
236}
237
238#endif