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 std::vector<ConstString>
99 Language::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic)
100 {
101     return {};
102 }
103 
104 lldb_private::formatters::StringPrinter::EscapingHelper
105 Language::GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType elem_type)
106 {
107     return StringPrinter::GetDefaultEscapingHelper(elem_type);
108 }
109 
110 struct language_name_pair {
111     const char *name;
112     LanguageType type;
113 };
114 
115 struct language_name_pair language_names[] =
116 {
117     // To allow GetNameForLanguageType to be a simple array lookup, the first
118     // part of this array must follow enum LanguageType exactly.
119     {   "unknown",          eLanguageTypeUnknown        },
120     {   "c89",              eLanguageTypeC89            },
121     {   "c",                eLanguageTypeC              },
122     {   "ada83",            eLanguageTypeAda83          },
123     {   "c++",              eLanguageTypeC_plus_plus    },
124     {   "cobol74",          eLanguageTypeCobol74        },
125     {   "cobol85",          eLanguageTypeCobol85        },
126     {   "fortran77",        eLanguageTypeFortran77      },
127     {   "fortran90",        eLanguageTypeFortran90      },
128     {   "pascal83",         eLanguageTypePascal83       },
129     {   "modula2",          eLanguageTypeModula2        },
130     {   "java",             eLanguageTypeJava           },
131     {   "c99",              eLanguageTypeC99            },
132     {   "ada95",            eLanguageTypeAda95          },
133     {   "fortran95",        eLanguageTypeFortran95      },
134     {   "pli",              eLanguageTypePLI            },
135     {   "objective-c",      eLanguageTypeObjC           },
136     {   "objective-c++",    eLanguageTypeObjC_plus_plus },
137     {   "upc",              eLanguageTypeUPC            },
138     {   "d",                eLanguageTypeD              },
139     {   "python",           eLanguageTypePython         },
140     {   "opencl",           eLanguageTypeOpenCL         },
141     {   "go",               eLanguageTypeGo             },
142     {   "modula3",          eLanguageTypeModula3        },
143     {   "haskell",          eLanguageTypeHaskell        },
144     {   "c++03",            eLanguageTypeC_plus_plus_03 },
145     {   "c++11",            eLanguageTypeC_plus_plus_11 },
146     {   "ocaml",            eLanguageTypeOCaml          },
147     {   "rust",             eLanguageTypeRust           },
148     {   "c11",              eLanguageTypeC11            },
149     {   "swift",            eLanguageTypeSwift          },
150     {   "julia",            eLanguageTypeJulia          },
151     {   "dylan",            eLanguageTypeDylan          },
152     {   "c++14",            eLanguageTypeC_plus_plus_14 },
153     {   "fortran03",        eLanguageTypeFortran03      },
154     {   "fortran08",        eLanguageTypeFortran08      },
155     // Vendor Extensions
156     {   "mipsassem",        eLanguageTypeMipsAssembler  },
157     {   "renderscript",     eLanguageTypeExtRenderScript},
158     // Now synonyms, in arbitrary order
159     {   "objc",             eLanguageTypeObjC           },
160     {   "objc++",           eLanguageTypeObjC_plus_plus },
161     {   "pascal",           eLanguageTypePascal83       }
162 };
163 
164 static uint32_t num_languages = sizeof(language_names) / sizeof (struct language_name_pair);
165 
166 LanguageType
167 Language::GetLanguageTypeFromString (const char *string)
168 {
169     for (uint32_t i = 0; i < num_languages; i++)
170     {
171         if (strcasecmp (language_names[i].name, string) == 0)
172             return (LanguageType) language_names[i].type;
173     }
174     return eLanguageTypeUnknown;
175 }
176 
177 const char *
178 Language::GetNameForLanguageType (LanguageType language)
179 {
180     if (language < num_languages)
181         return language_names[language].name;
182     else
183         return language_names[eLanguageTypeUnknown].name;
184 }
185 
186 void
187 Language::PrintAllLanguages (Stream &s, const char *prefix, const char *suffix)
188 {
189     for (uint32_t i = 1; i < num_languages; i++)
190     {
191         s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
192     }
193 }
194 
195 void
196 Language::ForAllLanguages (std::function<bool(lldb::LanguageType)> callback)
197 {
198     for (uint32_t i = 1; i < num_languages; i++)
199     {
200         if (!callback(language_names[i].type))
201             break;
202     }
203 }
204 
205 bool
206 Language::LanguageIsCPlusPlus (LanguageType language)
207 {
208     switch (language)
209     {
210         case eLanguageTypeC_plus_plus:
211         case eLanguageTypeC_plus_plus_03:
212         case eLanguageTypeC_plus_plus_11:
213         case eLanguageTypeC_plus_plus_14:
214             return true;
215         default:
216             return false;
217     }
218 }
219 
220 bool
221 Language::LanguageIsObjC (LanguageType language)
222 {
223     switch (language)
224     {
225         case eLanguageTypeObjC:
226         case eLanguageTypeObjC_plus_plus:
227             return true;
228         default:
229             return false;
230     }
231 }
232 
233 bool
234 Language::LanguageIsC (LanguageType language)
235 {
236     switch (language)
237     {
238         case eLanguageTypeC:
239         case eLanguageTypeC89:
240         case eLanguageTypeC99:
241         case eLanguageTypeC11:
242             return true;
243         default:
244             return false;
245     }
246 }
247 
248 bool
249 Language::LanguageIsPascal (LanguageType language)
250 {
251     switch (language)
252     {
253         case eLanguageTypePascal83:
254             return true;
255         default:
256             return false;
257     }
258 }
259 
260 //----------------------------------------------------------------------
261 // Constructor
262 //----------------------------------------------------------------------
263 Language::Language()
264 {
265 }
266 
267 //----------------------------------------------------------------------
268 // Destructor
269 //----------------------------------------------------------------------
270 Language::~Language()
271 {
272 }
273