aboutsummaryrefslogtreecommitdiff
path: root/gcc/cobol/dts.h
diff options
context:
space:
mode:
authorJames K. Lowden <jklowden@symas.com>2025-03-06 16:25:09 -0500
committerRichard Biener <rguenth@gcc.gnu.org>2025-03-11 07:48:21 +0100
commit3c5ed996ac94a15bc2929155f2c69cc85eef89f7 (patch)
treec365f6e25814ca3e88ae3fed34ca7a327a016540 /gcc/cobol/dts.h
parenta0754187274a36443707eab5506ae53ab1d71ad2 (diff)
downloadgcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.zip
gcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.tar.gz
gcc-3c5ed996ac94a15bc2929155f2c69cc85eef89f7.tar.bz2
COBOL: Frontend
gcc/cobol/ * LICENSE: New file. * Make-lang.in: New file. * config-lang.in: New file. * lang.opt: New file. * lang.opt.urls: New file. * cbldiag.h: New file. * cdfval.h: New file. * cobol-system.h: New file. * copybook.h: New file. * dts.h: New file. * exceptg.h: New file. * gengen.h: New file. * genmath.h: New file. * genutil.h: New file. * inspect.h: New file. * lang-specs.h: New file. * lexio.h: New file. * parse_ante.h: New file. * parse_util.h: New file. * scan_ante.h: New file. * scan_post.h: New file. * show_parse.h: New file. * structs.h: New file. * symbols.h: New file. * token_names.h: New file. * util.h: New file. * cdf-copy.cc: New file. * lexio.cc: New file. * scan.l: New file. * parse.y: New file. * genapi.cc: New file. * genapi.h: New file. * gengen.cc: New file. * genmath.cc: New file. * genutil.cc: New file. * cdf.y: New file. * cobol1.cc: New file. * convert.cc: New file. * except.cc: New file. * gcobolspec.cc: New file. * structs.cc: New file. * symbols.cc: New file. * symfind.cc: New file. * util.cc: New file. * gcobc: New file. * gcobol.1: New file. * gcobol.3: New file. * help.gen: New file. * udf/stored-char-length.cbl: New file.
Diffstat (limited to 'gcc/cobol/dts.h')
-rw-r--r--gcc/cobol/dts.h109
1 files changed, 109 insertions, 0 deletions
diff --git a/gcc/cobol/dts.h b/gcc/cobol/dts.h
new file mode 100644
index 0000000..618f649
--- /dev/null
+++ b/gcc/cobol/dts.h
@@ -0,0 +1,109 @@
+/*
+ * Contributed to the public domain by James K. Lowden
+ * Tuesday October 17, 2023
+ *
+ * This stand-in for std::regex was written because the implementation provided
+ * by the GCC libstdc++ in GCC 11 proved too slow, where "slow" means "appears
+ * not to terminate". Some invocations of std::regex_search took over 5
+ * seconds (or minutes) and used over 1900 stack frames, and "never" returned.
+ * Because the same patterns and input presented no difficulty to the C standad
+ * library regex functions, I recast the C++ implementation in terms of
+ * regex(3).
+ *
+ * Unlike std::regex, this dts version supports only Posix EREs, and requires
+ * the input to be NUL-terminated.
+ *
+ * It is my hope and expectation to replace this implementation with the
+ * standard one when it is improved.
+ */
+
+#include <stdexcept>
+#include <vector>
+
+#include <regex.h>
+
+namespace dts {
+ class csub_match : public regmatch_t {
+ const char *input;
+ public:
+ const char *first, *second;
+ bool matched;
+
+ explicit csub_match( const char *input = NULL)
+ : input(input)
+ , first(NULL), second(NULL), matched(false)
+ {
+ static regmatch_t empty = { -1, -1 };
+ regmatch_t& self(*this);
+ self = empty;
+ }
+ csub_match( const char input[], const regmatch_t& m )
+ : input(input)
+ {
+ regmatch_t& self(*this);
+ self = m;
+ matched = rm_so != -1;
+ first = rm_so == -1? NULL : input + rm_so;
+ second = rm_eo == -1? NULL : input + rm_eo;
+ }
+
+ int length() const { return rm_eo - rm_so; }
+ };
+
+ typedef std::vector<csub_match> cmatch;
+
+ class regex : public regex_t {
+ size_t nsubexpr;
+ const char *pattern;
+ public:
+ enum cflag_t { extended = REG_EXTENDED, icase = REG_ICASE };
+
+ regex( const char pattern[], int flags ) : pattern(pattern) {
+ nsubexpr = 1 + std::count(pattern, pattern + strlen(pattern), '(');
+ int erc = regcomp(this, pattern, flags);
+ if( erc != 0 ) {
+ char msg[80];
+ regerror(erc, this, msg, sizeof msg);
+#if __cpp_exceptions
+ throw std::logic_error(msg);
+#else
+ pattern = NULL;
+ cbl_errx("%s", msg);
+#endif
+ }
+ }
+ ~regex() { regfree(this); }
+
+ size_t size() const { return nsubexpr; }
+ bool ready() const { return pattern != NULL; }
+ private:
+ regex( const regex& ) {}
+ };
+
+ inline bool regex_search( const char input[], const char *eoinput,
+ cmatch& cm, regex& re ) {
+ if( eoinput != NULL && *eoinput != '\0' ) {
+#if __cpp_exceptions
+ static const char msg[] = "input not NUL-terminated";
+ throw std::domain_error( msg );
+#else
+ eoinput = strchr(input, '\0');
+#endif
+ }
+ if( eoinput == NULL ) eoinput = strchr(input, '\0');
+ auto ncm = re.size();
+ cm.resize(ncm);
+ regmatch_t cms[ncm];
+
+
+ int erc = regexec( &re, input, ncm, cms, 0 );
+ if( erc != 0 ) return false;
+ std::transform( cms, cms+ncm, cm.begin(),
+ [input]( const regmatch_t& m ) {
+ return csub_match( input, m );
+ } );
+ return true;
+ }
+};
+
+