1 //===-- BreakpointID.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 // C Includes 11 #include <stdio.h> 12 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/Breakpoint.h" 17 #include "lldb/Breakpoint/BreakpointID.h" 18 #include "lldb/Core/Error.h" 19 #include "lldb/Core/Stream.h" 20 21 using namespace lldb; 22 using namespace lldb_private; 23 24 BreakpointID::BreakpointID(break_id_t bp_id, break_id_t loc_id) 25 : m_break_id(bp_id), m_location_id(loc_id) {} 26 27 BreakpointID::~BreakpointID() = default; 28 29 static llvm::StringRef g_range_specifiers[] = {"-", "to", "To", "TO"}; 30 31 // Tells whether or not STR is valid to use between two strings representing 32 // breakpoint IDs, to 33 // indicate a range of breakpoint IDs. This is broken out into a separate 34 // function so that we can 35 // easily change or add to the format for specifying ID ranges at a later date. 36 37 bool BreakpointID::IsRangeIdentifier(llvm::StringRef str) { 38 for (auto spec : g_range_specifiers) { 39 if (spec == str) 40 return true; 41 } 42 43 return false; 44 } 45 46 bool BreakpointID::IsValidIDExpression(llvm::StringRef str) { 47 return BreakpointID::ParseCanonicalReference(str).hasValue(); 48 } 49 50 llvm::ArrayRef<llvm::StringRef> BreakpointID::GetRangeSpecifiers() { 51 return llvm::makeArrayRef(g_range_specifiers); 52 } 53 54 void BreakpointID::GetDescription(Stream *s, lldb::DescriptionLevel level) { 55 if (level == eDescriptionLevelVerbose) 56 s->Printf("%p BreakpointID:", static_cast<void *>(this)); 57 58 if (m_break_id == LLDB_INVALID_BREAK_ID) 59 s->PutCString("<invalid>"); 60 else if (m_location_id == LLDB_INVALID_BREAK_ID) 61 s->Printf("%i", m_break_id); 62 else 63 s->Printf("%i.%i", m_break_id, m_location_id); 64 } 65 66 void BreakpointID::GetCanonicalReference(Stream *s, break_id_t bp_id, 67 break_id_t loc_id) { 68 if (bp_id == LLDB_INVALID_BREAK_ID) 69 s->PutCString("<invalid>"); 70 else if (loc_id == LLDB_INVALID_BREAK_ID) 71 s->Printf("%i", bp_id); 72 else 73 s->Printf("%i.%i", bp_id, loc_id); 74 } 75 76 llvm::Optional<BreakpointID> 77 BreakpointID::ParseCanonicalReference(llvm::StringRef input) { 78 break_id_t bp_id; 79 break_id_t loc_id = LLDB_INVALID_BREAK_ID; 80 81 if (input.empty()) 82 return llvm::None; 83 84 // If it doesn't start with an integer, it's not valid. 85 if (input.consumeInteger(0, bp_id)) 86 return llvm::None; 87 88 // period is optional, but if it exists, it must be followed by a number. 89 if (input.consume_front(".")) { 90 if (input.consumeInteger(0, loc_id)) 91 return llvm::None; 92 } 93 94 // And at the end, the entire string must have been consumed. 95 if (!input.empty()) 96 return llvm::None; 97 98 return BreakpointID(bp_id, loc_id); 99 } 100 101 bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Error &error) { 102 error.Clear(); 103 if (str.empty()) 104 return false; 105 106 // First character must be a letter or _ 107 if (!isalpha(str[0]) && str[0] != '_') 108 return false; 109 110 // Cannot contain ., -, or space. 111 if (str.find_first_of(".- ") != llvm::StringRef::npos) { 112 error.SetErrorStringWithFormat("invalid breakpoint name: \"%s\"", 113 str.str().c_str()); 114 return false; 115 } 116 117 return true; 118 } 119