1 //===-- Language.cpp -------------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include <functional>
11 #include <map>
12 #include <mutex>
13 
14 #include "lldb/Target/Language.h"
15 
16 #include "lldb/Host/Mutex.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Stream.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::formatters;
23 
24 typedef std::unique_ptr<Language> LanguageUP;
25 typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
26 
27 static LanguagesMap&
28 GetLanguagesMap ()
29 {
30     static LanguagesMap *g_map = nullptr;
31     static std::once_flag g_initialize;
32 
33     std::call_once(g_initialize, [] {
34         g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global destructor chain
35     });
36 
37     return *g_map;
38 }
39 static Mutex&
40 GetLanguagesMutex ()
41 {
42     static Mutex *g_mutex = nullptr;
43     static std::once_flag g_initialize;
44 
45     std::call_once(g_initialize, [] {
46         g_mutex = new Mutex(); // NOTE: INTENTIONAL LEAK due to global destructor chain
47     });
48 
49     return *g_mutex;
50 }
51 
52 Language*
53 Language::FindPlugin (lldb::LanguageType language)
54 {
55     Mutex::Locker locker(GetLanguagesMutex());
56     LanguagesMap& map(GetLanguagesMap());
57     auto iter = map.find(language), end = map.end();
58     if (iter != end)
59         return iter->second.get();
60 
61     Language *language_ptr = nullptr;
62     LanguageCreateInstance create_callback;
63 
64     for (uint32_t idx = 0;
65          (create_callback = PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
66          ++idx)
67     {
68         language_ptr = create_callback(language);
69 
70         if (language_ptr)
71         {
72             map[language] = std::unique_ptr<Language>(language_ptr);
73             return language_ptr;
74         }
75     }
76 
77     return nullptr;
78 }
79 
80 void
81 Language::ForEach (std::function<bool(Language*)> callback)
82 {
83     Mutex::Locker locker(GetLanguagesMutex());
84     LanguagesMap& map(GetLanguagesMap());
85     for (const auto& entry : map)
86     {
87         if (!callback(entry.second.get()))
88             break;
89     }
90 }
91 
92 lldb::TypeCategoryImplSP
93 Language::GetFormatters ()
94 {
95     return nullptr;
96 }
97 
98 HardcodedFormatters::HardcodedFormatFinder
99 Language::GetHardcodedFormats ()
100 {
101     return {};
102 }
103 
104 HardcodedFormatters::HardcodedSummaryFinder
105 Language::GetHardcodedSummaries ()
106 {
107     return {};
108 }
109 
110 HardcodedFormatters::HardcodedSyntheticFinder
111 Language::GetHardcodedSynthetics ()
112 {
113     return {};
114 }
115 
116 HardcodedFormatters::HardcodedValidatorFinder
117 Language::GetHardcodedValidators ()
118 {
119     return {};
120 }
121 
122 std::vector<ConstString>
123 Language::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
124 {
125     return {};
126 }
127 
128 lldb_private::formatters::StringPrinter::EscapingHelper
129 Language::GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType elem_type)
130 {
131     return StringPrinter::GetDefaultEscapingHelper(elem_type);
132 }
133 
134 struct language_name_pair {
135     const char *name;
136     LanguageType type;
137 };
138 
139 struct language_name_pair language_names[] =
140 {
141     // To allow GetNameForLanguageType to be a simple array lookup, the first
142     // part of this array must follow enum LanguageType exactly.
143     {   "unknown",          eLanguageTypeUnknown        },
144     {   "c89",              eLanguageTypeC89            },
145     {   "c",                eLanguageTypeC              },
146     {   "ada83",            eLanguageTypeAda83          },
147     {   "c++",              eLanguageTypeC_plus_plus    },
148     {   "cobol74",          eLanguageTypeCobol74        },
149     {   "cobol85",          eLanguageTypeCobol85        },
150     {   "fortran77",        eLanguageTypeFortran77      },
151     {   "fortran90",        eLanguageTypeFortran90      },
152     {   "pascal83",         eLanguageTypePascal83       },
153     {   "modula2",          eLanguageTypeModula2        },
154     {   "java",             eLanguageTypeJava           },
155     {   "c99",              eLanguageTypeC99            },
156     {   "ada95",            eLanguageTypeAda95          },
157     {   "fortran95",        eLanguageTypeFortran95      },
158     {   "pli",              eLanguageTypePLI            },
159     {   "objective-c",      eLanguageTypeObjC           },
160     {   "objective-c++",    eLanguageTypeObjC_plus_plus },
161     {   "upc",              eLanguageTypeUPC            },
162     {   "d",                eLanguageTypeD              },
163     {   "python",           eLanguageTypePython         },
164     {   "opencl",           eLanguageTypeOpenCL         },
165     {   "go",               eLanguageTypeGo             },
166     {   "modula3",          eLanguageTypeModula3        },
167     {   "haskell",          eLanguageTypeHaskell        },
168     {   "c++03",            eLanguageTypeC_plus_plus_03 },
169     {   "c++11",            eLanguageTypeC_plus_plus_11 },
170     {   "ocaml",            eLanguageTypeOCaml          },
171     {   "rust",             eLanguageTypeRust           },
172     {   "c11",              eLanguageTypeC11            },
173     {   "swift",            eLanguageTypeSwift          },
174     {   "julia",            eLanguageTypeJulia          },
175     {   "dylan",            eLanguageTypeDylan          },
176     {   "c++14",            eLanguageTypeC_plus_plus_14 },
177     {   "fortran03",        eLanguageTypeFortran03      },
178     {   "fortran08",        eLanguageTypeFortran08      },
179     // Vendor Extensions
180     {   "mipsassem",        eLanguageTypeMipsAssembler  },
181     {   "renderscript",     eLanguageTypeExtRenderScript},
182     // Now synonyms, in arbitrary order
183     {   "objc",             eLanguageTypeObjC           },
184     {   "objc++",           eLanguageTypeObjC_plus_plus },
185     {   "pascal",           eLanguageTypePascal83       }
186 };
187 
188 static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
189 
190 LanguageType
191 Language::GetLanguageTypeFromString (const char *string)
192 {
193     for (uint32_t i = 0; i < num_languages; i++)
194     {
195         if (strcasecmp (language_names[i].name, string) == 0)
196             return (LanguageType) language_names[i].type;
197     }
198     return eLanguageTypeUnknown;
199 }
200 
201 const char *
202 Language::GetNameForLanguageType (LanguageType language)
203 {
204     if (language < num_languages)
205         return language_names[language].name;
206     else
207         return language_names[eLanguageTypeUnknown].name;
208 }
209 
210 void
211 Language::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
212 {
213     for (uint32_t i = 1; i < num_languages; i++)
214     {
215         s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
216     }
217 }
218 
219 void
220 Language::ForAllLanguages (std::function<bool(lldb::LanguageType)> callback)
221 {
222     for (uint32_t i = 1; i < num_languages; i++)
223     {
224         if (!callback(language_names[i].type))
225             break;
226     }
227 }
228 
229 bool
230 Language::LanguageIsCPlusPlus (LanguageType language)
231 {
232     switch (language)
233     {
234         case eLanguageTypeC_plus_plus:
235         case eLanguageTypeC_plus_plus_03:
236         case eLanguageTypeC_plus_plus_11:
237         case eLanguageTypeC_plus_plus_14:
238             return true;
239         default:
240             return false;
241     }
242 }
243 
244 bool
245 Language::LanguageIsObjC (LanguageType language)
246 {
247     switch (language)
248     {
249         case eLanguageTypeObjC:
250         case eLanguageTypeObjC_plus_plus:
251             return true;
252         default:
253             return false;
254     }
255 }
256 
257 bool
258 Language::LanguageIsC (LanguageType language)
259 {
260     switch (language)
261     {
262         case eLanguageTypeC:
263         case eLanguageTypeC89:
264         case eLanguageTypeC99:
265         case eLanguageTypeC11:
266             return true;
267         default:
268             return false;
269     }
270 }
271 
272 bool
273 Language::LanguageIsPascal (LanguageType language)
274 {
275     switch (language)
276     {
277         case eLanguageTypePascal83:
278             return true;
279         default:
280             return false;
281     }
282 }
283 
284 //----------------------------------------------------------------------
285 // Constructor
286 //----------------------------------------------------------------------
287 Language::Language()
288 {
289 }
290 
291 //----------------------------------------------------------------------
292 // Destructor
293 //----------------------------------------------------------------------
294 Language::~Language()
295 {
296 }
297