blob: 7bb362a592ea3ad2c7c35fec81e795075adaa50d [file]
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Implementation of regcomp.
///
//===----------------------------------------------------------------------===//
#include "src/regex/regcomp.h"
#include "hdr/regex_macros.h"
#include "src/__support/CPP/new.h"
#include "src/__support/CPP/scope.h"
#include "src/__support/CPP/string_view.h"
#include "src/__support/alloc-checker.h"
#include "src/__support/common.h"
#include "src/__support/error_or.h"
#include "src/__support/macros/config.h"
#include "src/__support/macros/null_check.h"
#include "src/__support/regex/regex_ast.h"
#include "src/__support/regex/regex_internal.h"
#include "src/__support/regex/regex_parser.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, regcomp,
(regex_t *__restrict preg, const char *__restrict pattern,
int cflags)) {
LIBC_CRASH_ON_NULLPTR(preg);
LIBC_CRASH_ON_NULLPTR(pattern);
// Note: POSIX requires callers to call regfree() before reusing a preg
// object. We therefore do not attempt to free any previous __internal here
// as preg is uninitialised on first use and the pointer would be garbage.
// However, we clear __internal and re_nsub immediately so calling regfree()
// after a failed regcomp() is guaranteed to be a safe no-op.
preg->__internal = nullptr;
preg->re_nsub = 0;
// TODO: Enable BRE (!(cflags & REG_EXTENDED)), REG_ICASE, and REG_NOSPEC as
// each feature is implemented in subsequent patches.
if (!(cflags & REG_EXTENDED) ||
(cflags & ~(REG_EXTENDED | REG_NOSUB | REG_NEWLINE)) != 0)
return REG_BADPAT;
// TODO: Once cpp::unique_ptr and AllocChecker-backed cpp::make_unique are
// available in src/__support/CPP/, manage RegexInternal via unique_ptr so
// error paths do not require a scope guard.
AllocChecker ac;
regex::RegexInternal *internal = new (ac) regex::RegexInternal();
if (!ac)
return REG_ESPACE;
cpp::scope_exit internal_guard([internal] { delete internal; });
ErrorOr<regex::ExprId> root =
regex::parse_ere(cpp::string_view(pattern), cflags, internal->pool);
if (!root.has_value())
return root.error();
internal_guard.release();
internal->root = *root;
internal->cflags = cflags;
preg->__internal = internal;
return 0;
}
} // namespace LIBC_NAMESPACE_DECL