1 //===-- TypeCategory.cpp --------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/DataFormatters/TypeCategory.h" 10 #include "lldb/Target/Language.h" 11 12 13 using namespace lldb; 14 using namespace lldb_private; 15 16 TypeCategoryImpl::TypeCategoryImpl(IFormatChangeListener *clist, 17 ConstString name) 18 : m_format_cont(clist), m_summary_cont(clist), m_filter_cont(clist), 19 m_synth_cont(clist), m_enabled(false), m_change_listener(clist), 20 m_mutex(), m_name(name), m_languages() {} 21 22 static bool IsApplicable(lldb::LanguageType category_lang, 23 lldb::LanguageType valobj_lang) { 24 switch (category_lang) { 25 // Unless we know better, allow only exact equality. 26 default: 27 return category_lang == valobj_lang; 28 29 // the C family, we consider it as one 30 case eLanguageTypeC89: 31 case eLanguageTypeC: 32 case eLanguageTypeC99: 33 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC || 34 valobj_lang == eLanguageTypeC99; 35 36 // ObjC knows about C and itself 37 case eLanguageTypeObjC: 38 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC || 39 valobj_lang == eLanguageTypeC99 || valobj_lang == eLanguageTypeObjC; 40 41 // C++ knows about C and C++ 42 case eLanguageTypeC_plus_plus: 43 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC || 44 valobj_lang == eLanguageTypeC99 || 45 valobj_lang == eLanguageTypeC_plus_plus; 46 47 // ObjC++ knows about C,C++,ObjC and ObjC++ 48 case eLanguageTypeObjC_plus_plus: 49 return valobj_lang == eLanguageTypeC89 || valobj_lang == eLanguageTypeC || 50 valobj_lang == eLanguageTypeC99 || 51 valobj_lang == eLanguageTypeC_plus_plus || 52 valobj_lang == eLanguageTypeObjC; 53 54 // Categories with unspecified language match everything. 55 case eLanguageTypeUnknown: 56 return true; 57 } 58 } 59 60 bool TypeCategoryImpl::IsApplicable(lldb::LanguageType lang) { 61 for (size_t idx = 0; idx < GetNumLanguages(); idx++) { 62 const lldb::LanguageType category_lang = GetLanguageAtIndex(idx); 63 if (::IsApplicable(category_lang, lang)) 64 return true; 65 } 66 return false; 67 } 68 69 size_t TypeCategoryImpl::GetNumLanguages() { 70 if (m_languages.empty()) 71 return 1; 72 return m_languages.size(); 73 } 74 75 lldb::LanguageType TypeCategoryImpl::GetLanguageAtIndex(size_t idx) { 76 if (m_languages.empty()) 77 return lldb::eLanguageTypeUnknown; 78 return m_languages[idx]; 79 } 80 81 void TypeCategoryImpl::AddLanguage(lldb::LanguageType lang) { 82 m_languages.push_back(lang); 83 } 84 85 bool TypeCategoryImpl::Get(lldb::LanguageType lang, 86 const FormattersMatchVector &candidates, 87 lldb::TypeFormatImplSP &entry) { 88 if (!IsEnabled() || !IsApplicable(lang)) 89 return false; 90 if (GetTypeFormatsContainer()->Get(candidates, entry)) 91 return true; 92 bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry); 93 return regex; 94 } 95 96 bool TypeCategoryImpl::Get(lldb::LanguageType lang, 97 const FormattersMatchVector &candidates, 98 lldb::TypeSummaryImplSP &entry) { 99 if (!IsEnabled() || !IsApplicable(lang)) 100 return false; 101 if (GetTypeSummariesContainer()->Get(candidates, entry)) 102 return true; 103 bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry); 104 return regex; 105 } 106 107 bool TypeCategoryImpl::Get(lldb::LanguageType lang, 108 const FormattersMatchVector &candidates, 109 lldb::SyntheticChildrenSP &entry) { 110 if (!IsEnabled() || !IsApplicable(lang)) 111 return false; 112 TypeFilterImpl::SharedPointer filter_sp; 113 // first find both Filter and Synth, and then check which is most recent 114 115 if (!GetTypeFiltersContainer()->Get(candidates, filter_sp)) 116 GetRegexTypeFiltersContainer()->Get(candidates, filter_sp); 117 118 bool pick_synth = false; 119 ScriptedSyntheticChildren::SharedPointer synth; 120 if (!GetTypeSyntheticsContainer()->Get(candidates, synth)) 121 GetRegexTypeSyntheticsContainer()->Get(candidates, synth); 122 if (!filter_sp.get() && !synth.get()) 123 return false; 124 else if (!filter_sp.get() && synth.get()) 125 pick_synth = true; 126 127 else if (filter_sp.get() && !synth.get()) 128 pick_synth = false; 129 130 else /*if (filter_sp.get() && synth.get())*/ 131 { 132 pick_synth = filter_sp->GetRevision() <= synth->GetRevision(); 133 } 134 if (pick_synth) { 135 entry = synth; 136 return true; 137 } else { 138 entry = filter_sp; 139 return true; 140 } 141 return false; 142 } 143 144 void TypeCategoryImpl::Clear(FormatCategoryItems items) { 145 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 146 GetTypeFormatsContainer()->Clear(); 147 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 148 GetRegexTypeFormatsContainer()->Clear(); 149 150 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 151 GetTypeSummariesContainer()->Clear(); 152 if ((items & eFormatCategoryItemRegexSummary) == 153 eFormatCategoryItemRegexSummary) 154 GetRegexTypeSummariesContainer()->Clear(); 155 156 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 157 GetTypeFiltersContainer()->Clear(); 158 if ((items & eFormatCategoryItemRegexFilter) == 159 eFormatCategoryItemRegexFilter) 160 GetRegexTypeFiltersContainer()->Clear(); 161 162 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 163 GetTypeSyntheticsContainer()->Clear(); 164 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 165 GetRegexTypeSyntheticsContainer()->Clear(); 166 } 167 168 bool TypeCategoryImpl::Delete(ConstString name, FormatCategoryItems items) { 169 bool success = false; 170 171 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 172 success = GetTypeFormatsContainer()->Delete(name) || success; 173 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 174 success = GetRegexTypeFormatsContainer()->Delete(name) || success; 175 176 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 177 success = GetTypeSummariesContainer()->Delete(name) || success; 178 if ((items & eFormatCategoryItemRegexSummary) == 179 eFormatCategoryItemRegexSummary) 180 success = GetRegexTypeSummariesContainer()->Delete(name) || success; 181 182 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 183 success = GetTypeFiltersContainer()->Delete(name) || success; 184 if ((items & eFormatCategoryItemRegexFilter) == 185 eFormatCategoryItemRegexFilter) 186 success = GetRegexTypeFiltersContainer()->Delete(name) || success; 187 188 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 189 success = GetTypeSyntheticsContainer()->Delete(name) || success; 190 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 191 success = GetRegexTypeSyntheticsContainer()->Delete(name) || success; 192 193 return success; 194 } 195 196 uint32_t TypeCategoryImpl::GetCount(FormatCategoryItems items) { 197 uint32_t count = 0; 198 199 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) 200 count += GetTypeFormatsContainer()->GetCount(); 201 if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) 202 count += GetRegexTypeFormatsContainer()->GetCount(); 203 204 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) 205 count += GetTypeSummariesContainer()->GetCount(); 206 if ((items & eFormatCategoryItemRegexSummary) == 207 eFormatCategoryItemRegexSummary) 208 count += GetRegexTypeSummariesContainer()->GetCount(); 209 210 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) 211 count += GetTypeFiltersContainer()->GetCount(); 212 if ((items & eFormatCategoryItemRegexFilter) == 213 eFormatCategoryItemRegexFilter) 214 count += GetRegexTypeFiltersContainer()->GetCount(); 215 216 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) 217 count += GetTypeSyntheticsContainer()->GetCount(); 218 if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) 219 count += GetRegexTypeSyntheticsContainer()->GetCount(); 220 221 return count; 222 } 223 224 bool TypeCategoryImpl::AnyMatches(ConstString type_name, 225 FormatCategoryItems items, bool only_enabled, 226 const char **matching_category, 227 FormatCategoryItems *matching_type) { 228 if (!IsEnabled() && only_enabled) 229 return false; 230 231 lldb::TypeFormatImplSP format_sp; 232 lldb::TypeSummaryImplSP summary_sp; 233 TypeFilterImpl::SharedPointer filter_sp; 234 ScriptedSyntheticChildren::SharedPointer synth_sp; 235 236 if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) { 237 if (GetTypeFormatsContainer()->Get(type_name, format_sp)) { 238 if (matching_category) 239 *matching_category = m_name.GetCString(); 240 if (matching_type) 241 *matching_type = eFormatCategoryItemValue; 242 return true; 243 } 244 } 245 if ((items & eFormatCategoryItemRegexValue) == 246 eFormatCategoryItemRegexValue) { 247 if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) { 248 if (matching_category) 249 *matching_category = m_name.GetCString(); 250 if (matching_type) 251 *matching_type = eFormatCategoryItemRegexValue; 252 return true; 253 } 254 } 255 256 if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) { 257 if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) { 258 if (matching_category) 259 *matching_category = m_name.GetCString(); 260 if (matching_type) 261 *matching_type = eFormatCategoryItemSummary; 262 return true; 263 } 264 } 265 if ((items & eFormatCategoryItemRegexSummary) == 266 eFormatCategoryItemRegexSummary) { 267 if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) { 268 if (matching_category) 269 *matching_category = m_name.GetCString(); 270 if (matching_type) 271 *matching_type = eFormatCategoryItemRegexSummary; 272 return true; 273 } 274 } 275 276 if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) { 277 if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) { 278 if (matching_category) 279 *matching_category = m_name.GetCString(); 280 if (matching_type) 281 *matching_type = eFormatCategoryItemFilter; 282 return true; 283 } 284 } 285 if ((items & eFormatCategoryItemRegexFilter) == 286 eFormatCategoryItemRegexFilter) { 287 if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) { 288 if (matching_category) 289 *matching_category = m_name.GetCString(); 290 if (matching_type) 291 *matching_type = eFormatCategoryItemRegexFilter; 292 return true; 293 } 294 } 295 296 if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) { 297 if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) { 298 if (matching_category) 299 *matching_category = m_name.GetCString(); 300 if (matching_type) 301 *matching_type = eFormatCategoryItemSynth; 302 return true; 303 } 304 } 305 if ((items & eFormatCategoryItemRegexSynth) == 306 eFormatCategoryItemRegexSynth) { 307 if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) { 308 if (matching_category) 309 *matching_category = m_name.GetCString(); 310 if (matching_type) 311 *matching_type = eFormatCategoryItemRegexSynth; 312 return true; 313 } 314 } 315 316 return false; 317 } 318 319 TypeCategoryImpl::FormatContainer::MapValueType 320 TypeCategoryImpl::GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp) { 321 FormatContainer::MapValueType retval; 322 323 if (type_sp) { 324 if (type_sp->IsRegex()) 325 GetRegexTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), 326 retval); 327 else 328 GetTypeFormatsContainer()->GetExact(ConstString(type_sp->GetName()), 329 retval); 330 } 331 332 return retval; 333 } 334 335 TypeCategoryImpl::SummaryContainer::MapValueType 336 TypeCategoryImpl::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp) { 337 SummaryContainer::MapValueType retval; 338 339 if (type_sp) { 340 if (type_sp->IsRegex()) 341 GetRegexTypeSummariesContainer()->GetExact( 342 ConstString(type_sp->GetName()), retval); 343 else 344 GetTypeSummariesContainer()->GetExact(ConstString(type_sp->GetName()), 345 retval); 346 } 347 348 return retval; 349 } 350 351 TypeCategoryImpl::FilterContainer::MapValueType 352 TypeCategoryImpl::GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp) { 353 FilterContainer::MapValueType retval; 354 355 if (type_sp) { 356 if (type_sp->IsRegex()) 357 GetRegexTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), 358 retval); 359 else 360 GetTypeFiltersContainer()->GetExact(ConstString(type_sp->GetName()), 361 retval); 362 } 363 364 return retval; 365 } 366 367 TypeCategoryImpl::SynthContainer::MapValueType 368 TypeCategoryImpl::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp) { 369 SynthContainer::MapValueType retval; 370 371 if (type_sp) { 372 if (type_sp->IsRegex()) 373 GetRegexTypeSyntheticsContainer()->GetExact( 374 ConstString(type_sp->GetName()), retval); 375 else 376 GetTypeSyntheticsContainer()->GetExact(ConstString(type_sp->GetName()), 377 retval); 378 } 379 380 return retval; 381 } 382 383 lldb::TypeNameSpecifierImplSP 384 TypeCategoryImpl::GetTypeNameSpecifierForSummaryAtIndex(size_t index) { 385 if (index < GetTypeSummariesContainer()->GetCount()) 386 return GetTypeSummariesContainer()->GetTypeNameSpecifierAtIndex(index); 387 else 388 return GetRegexTypeSummariesContainer()->GetTypeNameSpecifierAtIndex( 389 index - GetTypeSummariesContainer()->GetCount()); 390 } 391 392 TypeCategoryImpl::FormatContainer::MapValueType 393 TypeCategoryImpl::GetFormatAtIndex(size_t index) { 394 if (index < GetTypeFormatsContainer()->GetCount()) 395 return GetTypeFormatsContainer()->GetAtIndex(index); 396 else 397 return GetRegexTypeFormatsContainer()->GetAtIndex( 398 index - GetTypeFormatsContainer()->GetCount()); 399 } 400 401 TypeCategoryImpl::SummaryContainer::MapValueType 402 TypeCategoryImpl::GetSummaryAtIndex(size_t index) { 403 if (index < GetTypeSummariesContainer()->GetCount()) 404 return GetTypeSummariesContainer()->GetAtIndex(index); 405 else 406 return GetRegexTypeSummariesContainer()->GetAtIndex( 407 index - GetTypeSummariesContainer()->GetCount()); 408 } 409 410 TypeCategoryImpl::FilterContainer::MapValueType 411 TypeCategoryImpl::GetFilterAtIndex(size_t index) { 412 if (index < GetTypeFiltersContainer()->GetCount()) 413 return GetTypeFiltersContainer()->GetAtIndex(index); 414 else 415 return GetRegexTypeFiltersContainer()->GetAtIndex( 416 index - GetTypeFiltersContainer()->GetCount()); 417 } 418 419 lldb::TypeNameSpecifierImplSP 420 TypeCategoryImpl::GetTypeNameSpecifierForFormatAtIndex(size_t index) { 421 if (index < GetTypeFormatsContainer()->GetCount()) 422 return GetTypeFormatsContainer()->GetTypeNameSpecifierAtIndex(index); 423 else 424 return GetRegexTypeFormatsContainer()->GetTypeNameSpecifierAtIndex( 425 index - GetTypeFormatsContainer()->GetCount()); 426 } 427 428 lldb::TypeNameSpecifierImplSP 429 TypeCategoryImpl::GetTypeNameSpecifierForFilterAtIndex(size_t index) { 430 if (index < GetTypeFiltersContainer()->GetCount()) 431 return GetTypeFiltersContainer()->GetTypeNameSpecifierAtIndex(index); 432 else 433 return GetRegexTypeFiltersContainer()->GetTypeNameSpecifierAtIndex( 434 index - GetTypeFiltersContainer()->GetCount()); 435 } 436 437 TypeCategoryImpl::SynthContainer::MapValueType 438 TypeCategoryImpl::GetSyntheticAtIndex(size_t index) { 439 if (index < GetTypeSyntheticsContainer()->GetCount()) 440 return GetTypeSyntheticsContainer()->GetAtIndex(index); 441 else 442 return GetRegexTypeSyntheticsContainer()->GetAtIndex( 443 index - GetTypeSyntheticsContainer()->GetCount()); 444 } 445 446 lldb::TypeNameSpecifierImplSP 447 TypeCategoryImpl::GetTypeNameSpecifierForSyntheticAtIndex(size_t index) { 448 if (index < GetTypeSyntheticsContainer()->GetCount()) 449 return GetTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex(index); 450 else 451 return GetRegexTypeSyntheticsContainer()->GetTypeNameSpecifierAtIndex( 452 index - GetTypeSyntheticsContainer()->GetCount()); 453 } 454 455 void TypeCategoryImpl::Enable(bool value, uint32_t position) { 456 std::lock_guard<std::recursive_mutex> guard(m_mutex); 457 if ((m_enabled = value)) 458 m_enabled_position = position; 459 if (m_change_listener) 460 m_change_listener->Changed(); 461 } 462 463 std::string TypeCategoryImpl::GetDescription() { 464 StreamString stream; 465 stream.Printf("%s (%s", GetName(), (IsEnabled() ? "enabled" : "disabled")); 466 StreamString lang_stream; 467 lang_stream.Printf(", applicable for language(s): "); 468 bool print_lang = false; 469 for (size_t idx = 0; idx < GetNumLanguages(); idx++) { 470 const lldb::LanguageType lang = GetLanguageAtIndex(idx); 471 if (lang != lldb::eLanguageTypeUnknown) 472 print_lang = true; 473 lang_stream.Printf("%s%s", Language::GetNameForLanguageType(lang), 474 idx + 1 < GetNumLanguages() ? ", " : ""); 475 } 476 if (print_lang) 477 stream.PutCString(lang_stream.GetString()); 478 stream.PutChar(')'); 479 return std::string(stream.GetString()); 480 } 481