blob: 767521500af8a7f938c913ad31d1a195b9e8967e [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- RegularExpression.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
Greg Clayton7bd4c602015-01-21 21:51:02 +000010#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Core/RegularExpression.h"
Greg Clayton1b3815c2013-01-30 00:18:29 +000012#include "llvm/ADT/StringRef.h"
Greg Clayton7bd4c602015-01-21 21:51:02 +000013#include "lldb/Core/Error.h"
14
15
16//----------------------------------------------------------------------
17// Enable enhanced mode if it is available. This allows for things like
18// \d for digit, \s for space, and many more, but it isn't available
19// everywhere.
20//----------------------------------------------------------------------
21#if defined(REG_ENHANCED)
22#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED)
23#else
24#define DEFAULT_COMPILE_FLAGS (REG_EXTENDED)
25#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +000026
27using namespace lldb_private;
28
29//----------------------------------------------------------------------
30// Default constructor
31//----------------------------------------------------------------------
32RegularExpression::RegularExpression() :
33 m_re(),
34 m_comp_err (1),
Greg Clayton7bd4c602015-01-21 21:51:02 +000035 m_preg()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036{
37 memset(&m_preg,0,sizeof(m_preg));
38}
39
40//----------------------------------------------------------------------
41// Constructor that compiles "re" using "flags" and stores the
42// resulting compiled regular expression into this object.
43//----------------------------------------------------------------------
Jim Ingham969795f2011-09-21 01:17:13 +000044RegularExpression::RegularExpression(const char* re) :
45 m_re(),
46 m_comp_err (1),
Greg Clayton7bd4c602015-01-21 21:51:02 +000047 m_preg()
Jim Ingham969795f2011-09-21 01:17:13 +000048{
49 memset(&m_preg,0,sizeof(m_preg));
50 Compile(re);
51}
52
53RegularExpression::RegularExpression(const RegularExpression &rhs)
54{
55 memset(&m_preg,0,sizeof(m_preg));
Greg Clayton7bd4c602015-01-21 21:51:02 +000056 Compile(rhs.GetText());
Jim Ingham969795f2011-09-21 01:17:13 +000057}
58
59const RegularExpression &
60RegularExpression::operator= (const RegularExpression &rhs)
61{
62 if (&rhs != this)
Greg Clayton7bd4c602015-01-21 21:51:02 +000063 Compile (rhs.GetText());
Jim Ingham969795f2011-09-21 01:17:13 +000064 return *this;
65}
66//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067// Destructor
68//
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000069// Any previously compiled regular expression contained in this
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070// object will be freed.
71//----------------------------------------------------------------------
72RegularExpression::~RegularExpression()
73{
74 Free();
75}
76
77//----------------------------------------------------------------------
78// Compile a regular expression using the supplied regular
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000079// expression text and flags. The compiled regular expression lives
Chris Lattner30fdc8d2010-06-08 16:52:24 +000080// in this object so that it can be readily used for regular
81// expression matches. Execute() can be called after the regular
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000082// expression is compiled. Any previously compiled regular
Chris Lattner30fdc8d2010-06-08 16:52:24 +000083// expression contained in this object will be freed.
84//
85// RETURNS
Bruce Mitchenerd93c4a32014-07-01 21:22:11 +000086// True if the regular expression compiles successfully, false
Chris Lattner30fdc8d2010-06-08 16:52:24 +000087// otherwise.
88//----------------------------------------------------------------------
89bool
Jim Ingham969795f2011-09-21 01:17:13 +000090RegularExpression::Compile(const char* re)
91{
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092 Free();
Jim Ingham969795f2011-09-21 01:17:13 +000093
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094 if (re && re[0])
95 {
96 m_re = re;
Greg Clayton7bd4c602015-01-21 21:51:02 +000097 m_comp_err = ::regcomp (&m_preg, re, DEFAULT_COMPILE_FLAGS);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 }
99 else
100 {
101 // No valid regular expression
102 m_comp_err = 1;
103 }
104
105 return m_comp_err == 0;
106}
107
108//----------------------------------------------------------------------
109// Execute a regular expression match using the compiled regular
110// expression that is already in this object against the match
111// string "s". If any parens are used for regular expression
112// matches "match_count" should indicate the number of regmatch_t
113// values that are present in "match_ptr". The regular expression
114// will be executed using the "execute_flags".
Greg Claytonbc43cab2013-04-03 21:37:16 +0000115//---------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116bool
Greg Clayton7bd4c602015-01-21 21:51:02 +0000117RegularExpression::Execute (const char* s, Match *match) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000119 int err = 1;
Greg Claytoncc247752013-05-23 20:27:15 +0000120 if (s != NULL && m_comp_err == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000122 if (match)
Greg Clayton1b3815c2013-01-30 00:18:29 +0000123 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000124 err = ::regexec (&m_preg,
125 s,
126 match->GetSize(),
127 match->GetData(),
Greg Clayton7bd4c602015-01-21 21:51:02 +0000128 0);
Greg Claytonbc43cab2013-04-03 21:37:16 +0000129 }
130 else
131 {
132 err = ::regexec (&m_preg,
133 s,
134 0,
135 NULL,
Greg Clayton7bd4c602015-01-21 21:51:02 +0000136 0);
Greg Clayton1b3815c2013-01-30 00:18:29 +0000137 }
138 }
Greg Claytonbc43cab2013-04-03 21:37:16 +0000139
140 if (err != 0)
141 {
142 // The regular expression didn't compile, so clear the matches
143 if (match)
144 match->Clear();
145 return false;
146 }
147 return true;
Greg Clayton1b3815c2013-01-30 00:18:29 +0000148}
149
150bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000151RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152{
Greg Claytonfa226b72014-10-22 21:43:15 +0000153 llvm::StringRef match_str_ref;
154 if (GetMatchAtIndex(s, idx, match_str_ref))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155 {
Pavel Labath3a29f8b2015-07-28 09:18:32 +0000156 match_str = match_str_ref.str();
Greg Claytonfa226b72014-10-22 21:43:15 +0000157 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158 }
159 return false;
160}
161
Greg Clayton1b3815c2013-01-30 00:18:29 +0000162bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000163RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000164{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000165 if (idx < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000166 {
Greg Claytonfa226b72014-10-22 21:43:15 +0000167 if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1)
168 return false;
169
Greg Clayton1b3815c2013-01-30 00:18:29 +0000170 if (m_matches[idx].rm_eo == m_matches[idx].rm_so)
171 {
172 // Matched the empty string...
173 match_str = llvm::StringRef();
174 return true;
175 }
176 else if (m_matches[idx].rm_eo > m_matches[idx].rm_so)
177 {
178 match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so);
179 return true;
180 }
181 }
182 return false;
183}
184
185bool
Greg Claytonbc43cab2013-04-03 21:37:16 +0000186RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const
Greg Clayton1b3815c2013-01-30 00:18:29 +0000187{
Greg Claytonbc43cab2013-04-03 21:37:16 +0000188 if (idx1 < m_matches.size() && idx2 < m_matches.size())
Greg Clayton1b3815c2013-01-30 00:18:29 +0000189 {
190 if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo)
191 {
192 // Matched the empty string...
193 match_str = llvm::StringRef();
194 return true;
195 }
196 else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo)
197 {
198 match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so);
199 return true;
200 }
201 }
202 return false;
203}
204
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205
206//----------------------------------------------------------------------
207// Returns true if the regular expression compiled and is ready
208// for execution.
209//----------------------------------------------------------------------
210bool
211RegularExpression::IsValid () const
212{
213 return m_comp_err == 0;
214}
215
216//----------------------------------------------------------------------
217// Returns the text that was used to compile the current regular
218// expression.
219//----------------------------------------------------------------------
220const char*
221RegularExpression::GetText () const
222{
Greg Clayton67cc0632012-08-22 17:17:09 +0000223 if (m_re.empty())
224 return NULL;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225 return m_re.c_str();
226}
227
228//----------------------------------------------------------------------
229// Free any contained compiled regular expressions.
230//----------------------------------------------------------------------
231void
232RegularExpression::Free()
233{
234 if (m_comp_err == 0)
235 {
236 m_re.clear();
237 regfree(&m_preg);
238 // Set a compile error since we no longer have a valid regex
239 m_comp_err = 1;
240 }
241}
Greg Clayton46747022010-10-10 23:55:27 +0000242
243size_t
244RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const
245{
246 if (m_comp_err == 0)
247 {
248 if (err_str && err_str_max_len)
249 *err_str = '\0';
250 return 0;
251 }
252
253 return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len);
254}
255
Enrico Granata0a3958e2011-07-02 00:25:22 +0000256bool
257RegularExpression::operator < (const RegularExpression& rhs) const
258{
259 return (m_re < rhs.m_re);
260}