Change the regex_error_desc() interface. Have the caller pass in
a pointer to a buffer of at least BUFSZ characters and have
regex_error_desc() populate that. No need for static buffers or
extra dynamic alloction.
Also, change it to never return Null. None of its callers were
checking for that and could have passed Null to config_error_add()
or raw_print(). printf("%s", NULL) produces "null" on OSX but other
systems would probably crash if a Null result ever actually occurred.
The error explanation returned by cppregex included a trailing period.
config_error_add() adds one, so the message ended up with two. Have
regex_error_desc() check for final period and strip it off if found.
(My test case used a menucolor pattern of "[" which triggers an error
about mismatched brackets.)
Reformat cppregex.cpp; treat 'extern "C" {' as if it isn't introducing
a nested block. Fix the '#include <hack.h>' that 'make depend' was
ignoring.
91 lines
2.1 KiB
C++
91 lines
2.1 KiB
C++
/* NetHack 3.7 cppregex.cpp */
|
|
/* $NHDT-Date: 1596498279 2020/08/03 23:44:39 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.9 $ */
|
|
/* Copyright (c) Sean Hunt 2015. */
|
|
/* NetHack may be freely redistributed. See license for details. */
|
|
|
|
#include <regex>
|
|
#include <memory>
|
|
|
|
/* nhregex interface documented in sys/share/posixregex.c */
|
|
|
|
extern "C" { // rest of file
|
|
|
|
#include "config.h"
|
|
|
|
extern const char regex_id[] = "cppregex";
|
|
|
|
struct nhregex {
|
|
std::unique_ptr<std::regex> re;
|
|
std::unique_ptr<std::regex_error> err;
|
|
};
|
|
|
|
struct nhregex *
|
|
regex_init(void)
|
|
{
|
|
return new nhregex;
|
|
}
|
|
|
|
boolean
|
|
regex_compile(const char *s, struct nhregex *re)
|
|
{
|
|
if (!re)
|
|
return FALSE;
|
|
try {
|
|
re->re.reset(new std::regex(s, (std::regex::extended
|
|
| std::regex::nosubs
|
|
| std::regex::optimize)));
|
|
re->err.reset(nullptr);
|
|
return TRUE;
|
|
} catch (const std::regex_error& err) {
|
|
re->err.reset(new std::regex_error(err));
|
|
re->re.reset(nullptr);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
char *
|
|
regex_error_desc(struct nhregex *re, char *errbuf)
|
|
{
|
|
if (!re) {
|
|
Strcpy(errbuf, "no regexp");
|
|
} else if (!re->err) {
|
|
Strcpy(errbuf, "no explanation");
|
|
} else {
|
|
char *p;
|
|
|
|
errbuf[0] = '\0';
|
|
(void) strncat(errbuf, re->err->what(), BUFSZ - 1);
|
|
if (!errbuf[0])
|
|
Strcpy(errbuf, "unspecified regexp error");
|
|
|
|
/* caller will pass our result to config_error_add() and it adds
|
|
sentence ending period, so if the regex class error explanation
|
|
already ends in a period, strip that off */
|
|
if ((p = strrchr(errbuf, '.')) != 0 && !p[1])
|
|
*p = '\0';
|
|
}
|
|
return errbuf;
|
|
}
|
|
|
|
boolean
|
|
regex_match(const char *s, struct nhregex *re)
|
|
{
|
|
if (!re->re)
|
|
return false;
|
|
try {
|
|
return regex_search(s, *re->re, std::regex_constants::match_any);
|
|
} catch (const std::regex_error& err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void
|
|
regex_free(struct nhregex *re)
|
|
{
|
|
delete re;
|
|
}
|
|
|
|
} // extern "C"
|
|
|
|
/*cppregex.cpp*/
|