# flags
# do *not* add CXXFLAGS here, add them in configure.ac
AM_CXXFLAGS = $(CXXFLAGSDEFAULT)
+if DEBUG
+ AM_CXXFLAGS += -DRE2C_DEBUG
+endif
RE2CFLAGS = -b -W
# binary
src/util/attribute.h \
src/util/c99_stdint.h \
src/util/counter.h \
+ src/util/debug_assert.h \
src/util/forbid_copy.h \
src/util/free_list.h \
src/util/get_dir.h \
mkdir $builddir
cd $builddir
-../configure && \
+../configure --enable-debug && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" && \
+../configure --enable-debug CXXFLAGS="-fsanitize=address" LDFLAGS="-fsanitize=address" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CC=clang CXX=clang++ && \
+../configure --enable-debug CC=clang CXX=clang++ && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CC=clang CXX=clang++ CFLAGS="-fsanitize=memory" CXXFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory" && \
+../configure --enable-debug CC=clang CXX=clang++ CFLAGS="-fsanitize=memory" CXXFLAGS="-fsanitize=memory" LDFLAGS="-fsanitize=memory" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CXXFLAGS="-fsanitize=leak" LDFLAGS="-fsanitize=leak" && \
+../configure --enable-debug CXXFLAGS="-fsanitize=leak" LDFLAGS="-fsanitize=leak" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CXXFLAGS="-m32" LDFLAGS="-m32" && \
+../configure --enable-debug CXXFLAGS="-m32" LDFLAGS="-m32" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure --host i686-w64-mingw32 && \
+../configure --enable-debug --host i686-w64-mingw32 && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CFLAGS="-ffunction-sections -fdata-sections" LDFLAGS="-Wl,--gc-sections -Wl,--print-gc-sections" && \
+../configure --enable-debug CFLAGS="-ffunction-sections -fdata-sections" LDFLAGS="-Wl,--gc-sections -Wl,--print-gc-sections" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
-../configure CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined" && \
+../configure --enable-debug CXXFLAGS="-fsanitize=undefined" LDFLAGS="-fsanitize=undefined" && \
make -j5
cd ..
mkdir $builddir
cd $builddir
# 'make' implies 'make docs'; running both in parallel may cause data races
+ # configure without --enable-debug, this is the release binary
../configure --enable-docs \
&& $make_prog bootstrap -j5 \
&& $make_prog distcheck -j5
AC_SUBST(PACKAGE_RELEASE, ${PACKAGE_RELEASE:-1})
+# --enable-debug
+AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug],
+ [enable checks and assertions])])
+AM_CONDITIONAL([DEBUG], [test "x$enable_debug" = "xyes"])
+
+
# --enable-docs
AC_ARG_ENABLE([docs], [AS_HELP_STRING([--enable-docs], [regenerate manpage])])
AM_CONDITIONAL([REBUILD_DOCS], [test "x$enable_docs" = "xyes"])
#ifndef _RE2C_ADFA_ACTION_
#define _RE2C_ADFA_ACTION_
-#include <assert.h>
#include <vector>
#include "src/code/label.h"
#include "src/dfa/tcmd.h"
#include "src/util/c99_stdint.h"
+#include "src/util/debug_assert.h"
#include "src/util/uniq_vector.h"
namespace re2c
// already marked as initial, probably reuse mode
info.initial->label = label;
} else {
- assert(false);
+ DASSERT(false);
}
}
void set_save (size_t save)
{
- assert(type == MATCH);
+ DASSERT(type == MATCH);
type = SAVE;
info.save = save;
}
void set_move ()
{
- assert(type == MATCH);
+ DASSERT(type == MATCH);
type = MOVE;
}
void set_accept (const accept_t * accepts)
{
- assert(type == MATCH);
+ DASSERT(type == MATCH);
type = ACCEPT;
info.accepts = accepts;
}
void set_rule (size_t rule)
{
- assert(type == MATCH);
+ DASSERT(type == MATCH);
type = RULE;
info.rule = rule;
}
-#include <assert.h>
#include <algorithm>
#include <limits>
#include <queue>
#include "src/code/go.h"
#include "src/dfa/dfa.h"
#include "src/util/allocate.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
}
}
- assert(nStates == ord.size());
+ DASSERT(nStates == ord.size());
ord.push_back(NULL);
for(uint32_t i = 0; i < nStates; ++i)
-#include <assert.h>
#include "src/util/c99_stdint.h"
#include <string.h>
#include <algorithm>
#include "src/dfa/tcmd.h"
#include "src/re/rule.h"
#include "src/util/allocate.h"
+#include "src/util/debug_assert.h"
namespace re2c {
void DFA::hoist_tags_and_skip(const opt_t *opts)
{
- assert(opts->eager_skip);
+ DASSERT(opts->eager_skip);
for (State * s = head; s; s = s->next) {
Span *span = s->go.span;
-#include <assert.h>
#include <string.h>
#include "src/ast/scanner.h"
#include "src/conf/msg.h"
+#include "src/util/debug_assert.h"
namespace re2c {
// Find index of the current input file: the one corresponding to
// buffer fragment that contains cursor.
size_t i = files.size();
- assert(i > 0);
+ DASSERT(i > 0);
for (;;) {
--i;
Input *in = files[i];
bool Scanner::read(size_t want)
{
- assert(!files.empty());
+ DASSERT(!files.empty());
for (size_t i = files.size(); i --> 0; ) {
Input *in = files[i];
const size_t have = fread(lim, 1, want, in->file);
for (size_t i = files.size(); i --> 0; ) {
Input *in = files[i];
if (in->so == ENDPOS && in->eo == ENDPOS) break;
- assert(in->so != ENDPOS && in->eo != ENDPOS);
+ DASSERT(in->so != ENDPOS && in->eo != ENDPOS);
in->so += offs;
in->eo += offs;
}
// except for the first (main) file which must always remain at the
// bottom of the stack.
size_t i = files.size();
- assert(i > 0);
+ DASSERT(i > 0);
for (;;) {
--i;
Input *in = files[i];
pop_finished_files();
- assert(bot <= tok && tok <= lim);
+ DASSERT(bot <= tok && tok <= lim);
size_t free = static_cast<size_t>(tok - bot);
size_t copy = static_cast<size_t>(lim - tok);
-#include <assert.h>
#include <stddef.h>
#include "src/util/c99_stdint.h"
#include <iosfwd>
#include "src/re/tag.h"
#include "src/skeleton/skeleton.h"
#include "src/util/string_utils.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
o.wind(ind);
if (generic) {
- assert(dist == 0);
+ DASSERT(dist == 0);
if (!trailing(tag)) {
o.wstring(tagname(tag)).ws(" = ").wstring(expr);
} else if (!fixed_on_cursor) {
- assert(!dfa.oldstyle_ctxmarker);
+ DASSERT(!dfa.oldstyle_ctxmarker);
o.wstring(opts->yyrestoretag).ws(" (").wstring(expr).ws(")");
}
} else {
std::string tagname(const Tag &tag)
{
- assert(!trailing(tag));
+ DASSERT(!trailing(tag));
return capture(tag)
? "yypmatch[" + to_string(tag.ncap) + "]"
: *tag.name;
-#include <assert.h>
#include <stddef.h>
#include "src/util/c99_stdint.h"
#include <string>
#include "src/conf/opt.h"
#include "src/dfa/tcmd.h"
#include "src/util/allocate.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
: cases(new Case[nspans])
, cases_size(0)
{
- assert(nspans > 0);
+ DASSERT(nspans > 0);
// first case is default: book the place (ranges will be added later)
Case &c = cases[cases_size++];
-#include <assert.h>
#include <sstream>
#include "src/code/emit.h"
#include "src/code/input_api.h"
#include "src/conf/opt.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
void output_skip_peek(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yych << " = "
<< yych_conv(opts) << "*++" << opts->yycursor << ";\n";
}
void output_peek_skip(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yych << " = "
<< yych_conv(opts) << "*" << opts->yycursor << "++;\n";
}
void output_skip_backup(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yymarker << " = ++"
<< opts->yycursor << ";\n";
}
void output_backup_skip(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yymarker << " = "
<< opts->yycursor << "++;\n";
}
void output_backup_peek(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yych << " = "
<< yych_conv(opts) << "*(" << opts->yymarker << " = "
<< opts->yycursor << ");\n";
void output_skip_backup_peek(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yych << " = "
<< yych_conv(opts) << "*(" << opts->yymarker << " = ++"
<< opts->yycursor << ");\n";
void output_backup_peek_skip(std::ostream &o, uint32_t ind, const opt_t *opts)
{
- assert(opts->input_api == INPUT_DEFAULT);
+ DASSERT(opts->input_api == INPUT_DEFAULT);
o << indent(ind, opts->indString) << opts->yych << " = "
<< yych_conv(opts) << "*(" << opts->yymarker << " = "
<< opts->yycursor << "++);\n";
-#include <assert.h>
#include <string.h>
#include <vector>
#include "src/dfa/tcmd.h"
#include "src/re/rule.h"
#include "src/re/tag.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
bool *l = &live[i * nver];
// all final bblocks have USE tags, but no successors
- assert(r && b->succb == b->succe);
+ DASSERT(r && b->succb == b->succe);
for (size_t t = r->ltag; t < r->htag; ++t) {
l[fins[t]] = !fixed(tags[t]);
bool *old = &live[i * nver];
// transition bblocks have no USE tags
- assert(!b->rule);
+ DASSERT(!b->rule);
memcpy(buf1, old, nver * sizeof(bool));
for (cfg_ix_t *j = b->succb; j < b->succe; ++j) {
const Rule *r = b->rule;
// all fallback bblocks have USE tags
- assert(r);
+ DASSERT(r);
memset(buf1, 0, nver * sizeof(bool));
for (size_t t = r->ltag; t < r->htag; ++t) {
-#include <assert.h>
#include "src/util/c99_stdint.h"
#include <string.h>
#include <algorithm>
#include "src/dfa/dfa.h"
#include "src/dfa/tcmd.h"
#include "src/re/tag.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
static void swap(tcmd_t &x, tcmd_t &y)
{
- assert(!tcmd_t::isadd(&x) && !tcmd_t::isadd(&y));
+ DASSERT(!tcmd_t::isadd(&x) && !tcmd_t::isadd(&y));
std::swap(x.lhs, y.lhs);
std::swap(x.rhs, y.rhs);
std::swap(x.history[0], y.history[0]);
static bool less(const tcmd_t &x, const tcmd_t &y)
{
- assert(!tcmd_t::isadd(&x) && !tcmd_t::isadd(&y));
+ DASSERT(!tcmd_t::isadd(&x) && !tcmd_t::isadd(&y));
tagver_t u, v;
u = x.lhs; v = y.lhs;
-#include <assert.h>
#include "src/util/c99_stdint.h"
#include <stdlib.h>
#include <string.h>
#include "src/dfa/determinization.h"
#include "src/nfa/nfa.h"
+#include "src/util/debug_assert.h"
namespace re2c
q = i->state;
q->clos = NOCLOS;
q->arcidx = 0;
- assert(q->status == GOR_NOPASS && q->active == 0);
+ DASSERT(q->status == GOR_NOPASS && q->active == 0);
}
}
-#include <assert.h>
#include "src/util/c99_stdint.h"
#include <string.h>
#include <algorithm>
#include "src/nfa/nfa.h"
#include "src/re/rule.h"
#include "src/re/tag.h"
+#include "src/util/debug_assert.h"
#include "src/util/range.h"
const size_t ntags = dfa.tags.size();
// all-zero tag configuration must have static number zero
- assert(ZERO_TAGS == ctx.dc_tagvertbl.insert_const(TAGVER_ZERO));
+ DASSERT(ZERO_TAGS == ctx.dc_tagvertbl.insert_const(TAGVER_ZERO));
// initial tag versions: [1 .. N]
const uint32_t INITIAL_TAGS = ctx.dc_tagvertbl.insert_succ(1);
#include "src/nfa/nfa.h"
#include "src/re/rule.h"
#include "src/re/tag.h"
-
+#include "src/util/debug_assert.h"
namespace re2c
{
// see note [at most one final item per closure]
c = std::find_if(b, e, clos_t::fin);
- assert(c != e);
+ DASSERT(c != e);
fprintf(stderr, " r%u [shape=none label=\"(", state);
for (size_t t = r.ltag; t < r.htag; ++t) {
-#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include "src/dfa/tcmd.h"
#include "src/nfa/nfa.h"
#include "src/re/rule.h"
+#include "src/util/debug_assert.h"
#include "src/util/hash32.h"
bool equal_lookahead_tags(const kernel_t *x, const kernel_t *y, const determ_context_t &ctx)
{
- assert(x->size == y->size);
+ DASSERT(x->size == y->size);
if (memcmp(x->tlook, y->tlook, x->size * sizeof(hidx_t)) == 0) {
return true;
for (tagver_t xv = -max; xv < max; ++xv) {
const tagver_t yv = x2y[xv], axv = abs(xv), ayv = abs(yv);
if (yv != TAGVER_ZERO && xv != yv && !fixed(tags[x2t[xv]])) {
- assert(axv != ayv);
+ DASSERT(axv != ayv);
copy = ctx.dc_dfa.tcpool.make_copy(copy, axv, ayv);
}
}
-#include <assert.h>
#include <stdlib.h>
#include "src/dfa/determinization.h"
#include "src/dfa/tag_history.h"
+#include "src/util/debug_assert.h"
namespace re2c
const bool neg1 = j1->neg, neg2 = j2->neg;
// can't be both closing
- assert(!(idx1 % 2 == 1 && idx2 % 2 == 1));
+ DASSERT(!(idx1 % 2 == 1 && idx2 % 2 == 1));
// closing vs opening: closing wins
if (idx1 % 2 == 1) return -1;
if (idx2 % 2 == 1) return 1;
// can't be both negative
- assert(!(neg1 && neg2));
+ DASSERT(!(neg1 && neg2));
// positive vs negative: positive wins
if (neg1) return 1;
}
// unreachable
- assert(false);
+ DASSERT(false);
return 0;
}
uint32_t u_packed = (u_longest & 0x3fffFFFF) | (u_leftmost << 30u);
int32_t packed = static_cast<int32_t>(u_packed);
- assert(unpack_longest(packed) == longest
+ DASSERT(unpack_longest(packed) == longest
&& unpack_leftmost(packed) == leftmost);
return packed;
-#include <assert.h>
#include <string.h>
#include "src/dfa/tcmd.h"
+#include "src/util/debug_assert.h"
#include "src/util/hash32.h"
namespace re2c
bool tcmd_t::isset(const tcmd_t *x)
{
if (x->rhs == TAGVER_ZERO) {
- assert(x->history[0] != TAGVER_ZERO);
+ DASSERT(x->history[0] != TAGVER_ZERO);
return true;
}
return false;
, index()
{
// empty command must have static number zero
- assert(TCID0 == insert(NULL));
+ DASSERT(TCID0 == insert(NULL));
}
#ifndef _RE2C_RE_RE_
#define _RE2C_RE_RE_
-#include "src/util/c99_stdint.h"
-
#include "src/conf/opt.h"
#include "src/ast/ast.h"
#include "src/re/rule.h"
+#include "src/util/c99_stdint.h"
+#include "src/util/debug_assert.h"
#include "src/util/forbid_copy.h"
#include "src/util/range.h"
#include "src/util/slab_allocator.h"
RE *x = alc.alloct<RE>(1);
x->type = RE::TAG;
x->tag.idx = idx & 0x7FFFffff;
- assert(idx == x->tag.idx);
+ DASSERT(idx == x->tag.idx);
x->tag.neg = neg;
return x;
}
#include "src/re/tag.h"
-#include <assert.h>
#include <limits>
namespace re2c
-#include <assert.h>
#include <stddef.h>
#include "src/util/c99_stdint.h"
#include <stdio.h>
#include "src/re/tag.h"
#include "src/skeleton/path.h"
#include "src/skeleton/skeleton.h"
+#include "src/util/debug_assert.h"
#include "src/util/forbid_copy.h"
#include "src/util/u32lim.h"
#include "src/util/wrap_iter.h"
if (trail == htag) {
matched = f;
} else {
- assert(!fixed(skel.tags[trail])); // no fixed trailing context
+ DASSERT(!fixed(skel.tags[trail])); // no fixed trailing context
matched = tags[skel.finvers[trail]].back();
- assert(matched != Skeleton::DEFTAG);
+ DASSERT(matched != Skeleton::DEFTAG);
}
}
-#include <assert.h>
#include <stddef.h>
#include "src/util/c99_stdint.h"
#include <algorithm>
#include "src/conf/msg.h"
#include "src/skeleton/skeleton.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
const uint32_t d = calc_dist(skel, loops, dists, arc->first);
// not necessarily true for dists[arc->first]
- assert (d != DIST_ERROR);
+ DASSERT (d != DIST_ERROR);
dist = (dist == DIST_ERROR) ? d : std::max(dist, d);
}
-#include <assert.h>
#include <algorithm>
#include "src/dfa/dfa.h"
#include "src/skeleton/skeleton.h"
+#include "src/util/debug_assert.h"
namespace re2c
{
uint64_t rule2key(size_t rule, size_t key, size_t def)
{
switch (key) {
- default: assert(false); // shouldn't happen
+ default: DASSERT(false); // shouldn't happen
case 8: return rule2key<uint64_t>(rule, def);
case 4: return rule2key<uint32_t>(rule, def);
case 2: return rule2key<uint16_t>(rule, def);
--- /dev/null
+#ifndef _RE2C_UTIL_DEBUG_ASSERT_
+#define _RE2C_UTIL_DEBUG_ASSERT_
+
+#ifdef RE2C_DEBUG
+
+#include <assert.h>
+#define DASSERT(x) assert(x)
+
+#else // RE2C_DEBUG
+
+#define DASSERT(x)
+
+#endif // RE2C_DEBUG
+
+#endif // _RE2C_UTIL_DEBUG_ASSERT_
#define _RE2C_UTIL_LOOKUP_
#include "src/util/c99_stdint.h"
-#include <assert.h>
#include <limits>
#include <map>
#include <vector>
#include <stddef.h>
+#include "src/util/debug_assert.h"
+
namespace re2c
{
template<typename data_t, typename hash_t>
uint32_t lookup_t<data_t, hash_t>::push(hash_t hash, const data_t &data)
{
- assert(elems.size() < NIL);
+ DASSERT(elems.size() < NIL);
const uint32_t idx = static_cast<uint32_t>(elems.size());
elems.push_back(elem_t(head(hash), data));
lookup[hash] = idx;
#ifndef _RE2C_UTIL_RANGE_
#define _RE2C_UTIL_RANGE_
-#include <assert.h>
#include <stddef.h> // NULL
#include "src/util/c99_stdint.h"
#include "src/test/range/test.h"
+#include "src/util/debug_assert.h"
#include "src/util/forbid_copy.h"
#include "src/util/free_list.h"
, lb (l)
, ub (u)
{
- assert (lb < ub);
+ DASSERT(lb < ub);
vFreeList.insert (this);
}
static void append_overlapping (Range * & head, Range * & tail, const Range * r);