GDB (API)
/home/stan/gdb/src/gdb/d-lang.c
Go to the documentation of this file.
00001 /* D language support routines for GDB, the GNU debugger.
00002 
00003    Copyright (C) 2005-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "symtab.h"
00022 #include "language.h"
00023 #include "d-lang.h"
00024 #include "c-lang.h"
00025 #include "gdb_string.h"
00026 #include "parser-defs.h"
00027 #include "gdb_obstack.h"
00028 
00029 #include <ctype.h>
00030 
00031 /* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
00032    Return 1 on success or 0 on failure.  */
00033 static int
00034 extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
00035 {
00036   long i = 0;
00037 
00038   while (isdigit (*mangled_str))
00039     {
00040       char *end_ptr;
00041 
00042       i = strtol (mangled_str, &end_ptr, 10);
00043       mangled_str = end_ptr;
00044       if (i <= 0 || strlen (mangled_str) < i)
00045         return 0;
00046       obstack_grow (tempbuf, mangled_str, i);
00047       mangled_str += i;
00048       obstack_grow_str (tempbuf, ".");
00049     }
00050   if (*mangled_str == '\0' || i == 0)
00051     return 0;
00052   obstack_blank (tempbuf, -1);
00053   return 1;
00054 }
00055 
00056 /* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
00057    Return 1 on success or 0 on failure.  */
00058 static int
00059 extract_type_info (const char *mangled_str, struct obstack *tempbuf)
00060 {
00061   if (*mangled_str == '\0')
00062     return 0;
00063   switch (*mangled_str++)
00064     {
00065       case 'A': /* dynamic array */
00066       case 'G': /* static array */
00067       case 'H': /* associative array */
00068         if (!extract_type_info (mangled_str, tempbuf))
00069           return 0;
00070         obstack_grow_str (tempbuf, "[]");
00071         return 1;
00072       case 'P': /* pointer */
00073         if (!extract_type_info (mangled_str, tempbuf))
00074           return 0;
00075         obstack_grow_str (tempbuf, "*");
00076         return 1;
00077       case 'R': /* reference */
00078         if (!extract_type_info (mangled_str, tempbuf))
00079           return 0;
00080         obstack_grow_str (tempbuf, "&");
00081         return 1;
00082       case 'Z': /* return value */
00083         return extract_type_info (mangled_str, tempbuf);
00084       case 'J': /* out */
00085         obstack_grow_str (tempbuf, "out ");
00086         return extract_type_info (mangled_str, tempbuf);
00087       case 'K': /* inout */
00088         obstack_grow_str (tempbuf, "inout ");
00089         return extract_type_info (mangled_str, tempbuf);
00090       case 'E': /* enum */
00091       case 'T': /* typedef */
00092       case 'D': /* delegate */
00093       case 'C': /* class */
00094       case 'S': /* struct */
00095         return extract_identifiers (mangled_str, tempbuf);
00096 
00097       /* basic types: */
00098       case 'n': obstack_grow_str (tempbuf, "none"); return 1;
00099       case 'v': obstack_grow_str (tempbuf, "void"); return 1;
00100       case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
00101       case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
00102       case 's': obstack_grow_str (tempbuf, "short"); return 1;
00103       case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
00104       case 'i': obstack_grow_str (tempbuf, "int"); return 1;
00105       case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
00106       case 'l': obstack_grow_str (tempbuf, "long"); return 1;
00107       case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
00108       case 'f': obstack_grow_str (tempbuf, "float"); return 1;
00109       case 'd': obstack_grow_str (tempbuf, "double"); return 1;
00110       case 'e': obstack_grow_str (tempbuf, "real"); return 1;
00111 
00112       /* imaginary and complex: */
00113       case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
00114       case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
00115       case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
00116       case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
00117       case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
00118       case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
00119 
00120       /* other types: */
00121       case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
00122       case 'a': obstack_grow_str (tempbuf, "char"); return 1;
00123       case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
00124       case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
00125 
00126       default:
00127         obstack_grow_str (tempbuf, "unknown");
00128         return 1;
00129     }
00130 }
00131 
00132 /* Implements the la_demangle language_defn routine for language D.  */
00133 char *
00134 d_demangle (const char *symbol, int options)
00135 {
00136   struct obstack tempbuf;
00137   char *out_str;
00138   unsigned char is_func = 0;
00139 
00140   if (symbol == NULL)
00141     return NULL;
00142   else if (strcmp (symbol, "_Dmain") == 0)
00143     return xstrdup ("D main");
00144 
00145   obstack_init (&tempbuf);
00146   
00147   if (symbol[0] == '_' && symbol[1] == 'D')
00148     {
00149       symbol += 2;
00150       is_func = 1;
00151     }
00152   else if (strncmp (symbol, "__Class_", 8) == 0)
00153     symbol += 8;
00154   else if (strncmp (symbol, "__init_", 7) == 0)
00155     symbol += 7;
00156   else if (strncmp (symbol, "__vtbl_", 7) == 0)
00157     symbol += 7;
00158   else if (strncmp (symbol, "__modctor_", 10) == 0)
00159     symbol += 10;
00160   else if (strncmp (symbol, "__moddtor_", 10) == 0)
00161     symbol += 10;
00162   else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
00163     symbol += 13;
00164   else
00165     {
00166       obstack_free (&tempbuf, NULL);
00167       return NULL;
00168     }
00169   
00170   if (!extract_identifiers (symbol, &tempbuf))
00171     {
00172       obstack_free (&tempbuf, NULL);
00173       return NULL;
00174     }
00175 
00176   obstack_grow_str (&tempbuf, "(");
00177   if (is_func == 1 && *symbol == 'F')
00178     {
00179       symbol++;
00180       while (*symbol != '\0' && *symbol != 'Z')
00181         {
00182           if (is_func == 1)
00183             is_func++;
00184           else
00185             obstack_grow_str (&tempbuf, ", ");
00186           if (!extract_type_info (symbol, &tempbuf))
00187             {
00188               obstack_free (&tempbuf, NULL);
00189               return NULL;
00190            }
00191         }
00192      }
00193   obstack_grow_str0 (&tempbuf, ")");
00194 
00195   /* Doesn't display the return type, but wouldn't be too hard to do.  */
00196 
00197   out_str = xstrdup (obstack_finish (&tempbuf));
00198   obstack_free (&tempbuf, NULL);
00199   return out_str;
00200 }
00201 
00202 /* Table mapping opcodes into strings for printing operators
00203    and precedences of the operators.  */
00204 static const struct op_print d_op_print_tab[] =
00205 {
00206   {",", BINOP_COMMA, PREC_COMMA, 0},
00207   {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
00208   {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
00209   {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
00210   {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
00211   {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
00212   {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
00213   {"==", BINOP_EQUAL, PREC_EQUAL, 0},
00214   {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
00215   {"<=", BINOP_LEQ, PREC_ORDER, 0},
00216   {">=", BINOP_GEQ, PREC_ORDER, 0},
00217   {">", BINOP_GTR, PREC_ORDER, 0},
00218   {"<", BINOP_LESS, PREC_ORDER, 0},
00219   {">>", BINOP_RSH, PREC_SHIFT, 0},
00220   {"<<", BINOP_LSH, PREC_SHIFT, 0},
00221   {"+", BINOP_ADD, PREC_ADD, 0},
00222   {"-", BINOP_SUB, PREC_ADD, 0},
00223   {"*", BINOP_MUL, PREC_MUL, 0},
00224   {"/", BINOP_DIV, PREC_MUL, 0},
00225   {"%", BINOP_REM, PREC_MUL, 0},
00226   {"@", BINOP_REPEAT, PREC_REPEAT, 0},
00227   {"-", UNOP_NEG, PREC_PREFIX, 0},
00228   {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
00229   {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
00230   {"*", UNOP_IND, PREC_PREFIX, 0},
00231   {"&", UNOP_ADDR, PREC_PREFIX, 0},
00232   {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
00233   {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
00234   {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
00235   {NULL, 0, 0, 0}
00236 };
00237 
00238 static const struct language_defn d_language_defn =
00239 {
00240   "d",
00241   language_d,
00242   range_check_off,
00243   case_sensitive_on,
00244   array_row_major,
00245   macro_expansion_c,
00246   &exp_descriptor_c,
00247   c_parse,
00248   c_error,
00249   null_post_parser,
00250   c_printchar,                  /* Print a character constant.  */
00251   c_printstr,                   /* Function to print string constant.  */
00252   c_emit_char,                  /* Print a single char.  */
00253   c_print_type,                 /* Print a type using appropriate syntax.  */
00254   c_print_typedef,              /* Print a typedef using appropriate
00255                                    syntax.  */
00256   d_val_print,                  /* Print a value using appropriate syntax.  */
00257   c_value_print,                /* Print a top-level value.  */
00258   default_read_var_value,       /* la_read_var_value */
00259   NULL,                         /* Language specific skip_trampoline.  */
00260   "this",
00261   basic_lookup_symbol_nonlocal, 
00262   basic_lookup_transparent_type,
00263   d_demangle,                   /* Language specific symbol demangler.  */
00264   NULL,                         /* Language specific
00265                                    class_name_from_physname.  */
00266   d_op_print_tab,               /* Expression operators for printing.  */
00267   1,                            /* C-style arrays.  */
00268   0,                            /* String lower bound.  */
00269   default_word_break_characters,
00270   default_make_symbol_completion_list,
00271   c_language_arch_info,
00272   default_print_array_index,
00273   default_pass_by_reference,
00274   c_get_string,
00275   NULL,                         /* la_get_symbol_name_cmp */
00276   iterate_over_symbols,
00277   LANG_MAGIC
00278 };
00279 
00280 /* Provide a prototype to silence -Wmissing-prototypes.  */
00281 extern initialize_file_ftype _initialize_d_language;
00282 
00283 void
00284 _initialize_d_language (void)
00285 {
00286   add_language (&d_language_defn);
00287 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines