working on it

This commit is contained in:
Dawid Sobczak 2025-04-05 10:55:40 +01:00
parent 56a6e78765
commit 35a88970c2
1094 changed files with 51093 additions and 51 deletions

View file

@ -0,0 +1,150 @@
#include <fnmatch.h>
#include <wctype.h>
#include <string.h>
#include <wchar.h>
#include <stdlib.h>
#include <limits.h>
static int next(const char **s)
{
wchar_t c;
int l = mbtowc(&c, *s, MB_LEN_MAX);
/* hack to allow literal matches of invalid byte sequences */
if (l < 0) return (unsigned char)*(*s)++ - 0x100;
*s += l;
return c;
}
#define BRACKET_ERROR -0x100
#define BRACKET_NOCHAR -0x101
static int bracket_next(const char **s)
{
int c;
int type;
if (**s == '[') {
type = *(*s+1);
if (type == '.' || type == '=') {
*s += 2;
c = next(s);
if (c <= 0) return BRACKET_ERROR;
if (**s == type && *(*s+1) == ']') {
*s += 2;
return c;
}
for (; **s && (**s != type || *(*s+1) != ']'); (*s)++);
if (!**s) return BRACKET_ERROR;
*s += 2;
return BRACKET_NOCHAR;
}
}
c = next(s);
if (c <= 0) return BRACKET_ERROR;
return c;
}
#define __FNM_CONT 0x8000
int fnmatch(const char *p, const char *s, int flags)
{
int c, d, k;
int not;
int match;
int first;
int no_slash = (flags & FNM_PATHNAME) ? '/' : 0;
int no_period = (flags & FNM_PERIOD) && !(flags & __FNM_CONT) ? '.' : 0x100;
flags |= __FNM_CONT;
while ((c = *p++)) {
switch (c) {
case '?':
k = next(&s);
if (!k || k == no_period || k == no_slash)
return FNM_NOMATCH;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
c = *p++;
goto literal;
}
if (*s++ != c) return FNM_NOMATCH;
break;
case '*':
for (; *p == '*'; p++);
if (*p && !*s) return FNM_NOMATCH;
if (*s == no_period)
return FNM_NOMATCH;
if (!*p && (!no_slash || !strchr(s, no_slash)))
return 0;
for (; *s; s++)
if (!fnmatch(p, s, flags))
return 0;
else if (*s == no_slash)
break;
return FNM_NOMATCH;
case '[':
not = (*p == '!' || *p == '^');
if (not) p++;
k = next(&s);
if (!k || k == no_slash || k == no_period)
return FNM_NOMATCH;
match = 0;
first = 1;
for (;;) {
if (!*p) return FNM_NOMATCH;
if (*p == ']' && !first) break;
first = 0;
if (*p == '[' && *(p+1) == ':') {
const char *z;
p += 2;
for (z=p; *z && (*z != ':' || *(z+1) != ']'); z++);
if (!*z || z-p > 32) { /* FIXME: symbolic const? */
return FNM_NOMATCH;
} else {
char class[z-p+1];
memcpy(class, p, z-p);
class[z-p] = 0;
if (iswctype(k, wctype(class)))
match = 1;
}
p = z+2;
continue;
}
c = bracket_next(&p);
if (c == BRACKET_ERROR)
return FNM_NOMATCH;
if (c == BRACKET_NOCHAR)
continue;
if (*p == '-' && *(p+1) != ']') {
p++;
d = bracket_next(&p);
if (d == BRACKET_ERROR)
return FNM_NOMATCH;
if (d == BRACKET_NOCHAR)
continue;
if (k >= c && k <= d)
match = 1;
continue;
}
if (k == c) match = 1;
}
p++;
if (not == match)
return FNM_NOMATCH;
break;
default:
literal:
if (*s++ != c)
return FNM_NOMATCH;
if (c == no_slash && (flags & FNM_PERIOD)) {
no_period = '.';
continue;
}
break;
}
no_period = 0x100;
}
if (*s) return FNM_NOMATCH;
return 0;
}

View file

@ -0,0 +1,238 @@
#include <glob.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>
#include "libc.h"
struct match
{
struct match *next;
char name[1];
};
static int is_literal(const char *p, int useesc)
{
int bracket = 0;
for (; *p; p++) {
switch (*p) {
case '\\':
if (!useesc) break;
case '?':
case '*':
return 0;
case '[':
bracket = 1;
break;
case ']':
if (bracket) return 0;
break;
}
}
return 1;
}
static int append(struct match **tail, const char *name, size_t len, int mark)
{
struct match *new = malloc(sizeof(struct match) + len + 1);
if (!new) return -1;
(*tail)->next = new;
new->next = NULL;
strcpy(new->name, name);
if (mark) strcat(new->name, "/");
*tail = new;
return 0;
}
static int match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail)
{
DIR *dir;
long long de_buf[(sizeof(struct dirent) + NAME_MAX + sizeof(long long))/sizeof(long long)];
struct dirent *de;
char pat[strlen(p)+1];
char *p2;
size_t l = strlen(d);
int literal;
int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | FNM_PERIOD;
int error;
if ((p2 = strchr(p, '/'))) {
strcpy(pat, p);
pat[p2-p] = 0;
for (; *p2 == '/'; p2++);
p = pat;
}
literal = is_literal(p, !(flags & GLOB_NOESCAPE));
if (*d == '/' && !*(d+1)) l = 0;
/* rely on opendir failing for nondirectory objects */
dir = opendir(*d ? d : ".");
error = errno;
if (!dir) {
/* this is not an error -- we let opendir call stat for us */
if (error == ENOTDIR) return 0;
if (error == EACCES && !*p) {
struct stat st;
if (!stat(d, &st) && S_ISDIR(st.st_mode)) {
if (append(tail, d, l, l))
return GLOB_NOSPACE;
return 0;
}
}
if (errfunc(d, error) || (flags & GLOB_ERR))
return GLOB_ABORTED;
return 0;
}
if (!*p) {
error = append(tail, d, l, l) ? GLOB_NOSPACE : 0;
closedir(dir);
return error;
}
while (!(error = readdir_r(dir, (void *)de_buf, &de)) && de) {
char namebuf[l+de->d_reclen+2], *name = namebuf;
if (!literal && fnmatch(p, de->d_name, fnm_flags))
continue;
if (literal && strcmp(p, de->d_name))
continue;
if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12))
continue;
if (*d) {
memcpy(name, d, l);
name[l] = '/';
strcpy(name+l+1, de->d_name);
} else {
name = de->d_name;
}
if (p2) {
if ((error = match_in_dir(name, p2, flags, errfunc, tail))) {
closedir(dir);
return error;
}
} else {
int mark = 0;
if (flags & GLOB_MARK) {
if (de->d_type)
mark = S_ISDIR(de->d_type<<12);
else {
struct stat st;
stat(name, &st);
mark = S_ISDIR(st.st_mode);
}
}
if (append(tail, name, l+de->d_reclen+1, mark)) {
closedir(dir);
return GLOB_NOSPACE;
}
}
}
closedir(dir);
if (error && (errfunc(d, error) || (flags & GLOB_ERR)))
return GLOB_ABORTED;
return 0;
}
static int ignore_err(const char *path, int err)
{
return 0;
}
static void freelist(struct match *head)
{
struct match *match, *next;
for (match=head->next; match; match=next) {
next = match->next;
free(match);
}
}
static int sort(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
int glob(const char *pat, int flags, int (*errfunc)(const char *path, int err), glob_t *g)
{
const char *p=pat, *d;
struct match head = { .next = NULL }, *tail = &head;
size_t cnt, i;
size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0;
int error = 0;
if (*p == '/') {
for (; *p == '/'; p++);
d = "/";
} else {
d = "";
}
if (!errfunc) errfunc = ignore_err;
if (!(flags & GLOB_APPEND)) {
g->gl_offs = offs;
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
if (*p) error = match_in_dir(d, p, flags, errfunc, &tail);
if (error == GLOB_NOSPACE) {
freelist(&head);
return error;
}
for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++);
if (!cnt) {
if (flags & GLOB_NOCHECK) {
tail = &head;
if (append(&tail, pat, strlen(pat), 0))
return GLOB_NOSPACE;
cnt++;
} else
return GLOB_NOMATCH;
}
if (flags & GLOB_APPEND) {
char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *));
if (!pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
g->gl_pathv = pathv;
offs += g->gl_pathc;
} else {
g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *));
if (!g->gl_pathv) {
freelist(&head);
return GLOB_NOSPACE;
}
for (i=0; i<offs; i++)
g->gl_pathv[i] = NULL;
}
for (i=0, tail=head.next; i<cnt; tail=tail->next, i++)
g->gl_pathv[offs + i] = tail->name;
g->gl_pathv[offs + i] = NULL;
g->gl_pathc += cnt;
if (!(flags & GLOB_NOSORT))
qsort(g->gl_pathv+offs, cnt, sizeof(char *), sort);
return error;
}
void globfree(glob_t *g)
{
size_t i;
for (i=0; i<g->gl_pathc; i++)
free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name));
free(g->gl_pathv);
g->gl_pathc = 0;
g->gl_pathv = NULL;
}
LFS64(glob);
LFS64(globfree);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,75 @@
/*
regerror.c - POSIX regerror() implementation for TRE.
Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <string.h>
#include <regex.h>
/* Error message strings for error codes listed in `regex.h'. This list
needs to be in sync with the codes listed there, naturally. */
/* Converted to single string by Rich Felker to remove the need for
* data relocations at runtime, 27 Feb 2006. */
static const char tre_error_messages[] = {
"No error\0"
"No match\0"
"Invalid regexp\0"
"Unknown collating element\0"
"Unknown character class name\0"
"Trailing backslash\0"
"Invalid back reference\0"
"Missing ']'\0"
"Missing ')'\0"
"Missing '}'\0"
"Invalid contents of {}\0"
"Invalid character range\0"
"Out of memory\0"
"XXX\0"
};
size_t
regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
{
const char *err;
size_t err_len;
if (errcode >= 0 && errcode <= REG_BADRPT)
for (err=tre_error_messages; errcode; errcode--, err+=strlen(err)+1);
else
err = "Unknown error";
err_len = strlen(err) + 1;
if (errbuf_size > 0 && errbuf != NULL)
{
if (err_len > errbuf_size)
{
memcpy(errbuf, err, errbuf_size - 1);
errbuf[errbuf_size - 1] = '\0';
}
else
{
strcpy(errbuf, err);
}
}
return err_len;
}
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,163 @@
/*
tre-mem.c - TRE memory allocator
Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
This memory allocator is for allocating small memory blocks efficiently
in terms of memory overhead and execution speed. The allocated blocks
cannot be freed individually, only all at once. There can be multiple
allocators, though.
*/
#include <stdlib.h>
#include <string.h>
#include "tre.h"
/* Returns a new memory allocator or NULL if out of memory. */
tre_mem_t
tre_mem_new_impl(int provided, void *provided_block)
{
tre_mem_t mem;
if (provided)
{
mem = provided_block;
memset(mem, 0, sizeof(*mem));
}
else
mem = xcalloc(1, sizeof(*mem));
if (mem == NULL)
return NULL;
return mem;
}
/* Frees the memory allocator and all memory allocated with it. */
void
tre_mem_destroy(tre_mem_t mem)
{
tre_list_t *tmp, *l = mem->blocks;
while (l != NULL)
{
xfree(l->data);
tmp = l->next;
xfree(l);
l = tmp;
}
xfree(mem);
}
/* Allocates a block of `size' bytes from `mem'. Returns a pointer to the
allocated block or NULL if an underlying malloc() failed. */
void *
tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
int zero, size_t size)
{
void *ptr;
if (mem->failed)
{
DPRINT(("tre_mem_alloc: oops, called after failure?!\n"));
return NULL;
}
#ifdef MALLOC_DEBUGGING
if (!provided)
{
ptr = xmalloc(1);
if (ptr == NULL)
{
DPRINT(("tre_mem_alloc: xmalloc forced failure\n"));
mem->failed = 1;
return NULL;
}
xfree(ptr);
}
#endif /* MALLOC_DEBUGGING */
if (mem->n < size)
{
/* We need more memory than is available in the current block.
Allocate a new block. */
tre_list_t *l;
if (provided)
{
DPRINT(("tre_mem_alloc: using provided block\n"));
if (provided_block == NULL)
{
DPRINT(("tre_mem_alloc: provided block was NULL\n"));
mem->failed = 1;
return NULL;
}
mem->ptr = provided_block;
mem->n = TRE_MEM_BLOCK_SIZE;
}
else
{
int block_size;
if (size * 8 > TRE_MEM_BLOCK_SIZE)
block_size = size * 8;
else
block_size = TRE_MEM_BLOCK_SIZE;
DPRINT(("tre_mem_alloc: allocating new %d byte block\n",
block_size));
l = xmalloc(sizeof(*l));
if (l == NULL)
{
mem->failed = 1;
return NULL;
}
l->data = xmalloc(block_size);
if (l->data == NULL)
{
xfree(l);
mem->failed = 1;
return NULL;
}
l->next = NULL;
if (mem->current != NULL)
mem->current->next = l;
if (mem->blocks == NULL)
mem->blocks = l;
mem->current = l;
mem->ptr = l->data;
mem->n = block_size;
}
}
/* Make sure the next pointer will be aligned. */
size += ALIGN(mem->ptr + size, long);
/* Allocate from current block. */
ptr = mem->ptr;
mem->ptr += size;
mem->n -= size;
/* Set to zero if needed. */
if (zero)
memset(ptr, 0, size);
return ptr;
}
/* EOF */

View file

@ -0,0 +1,269 @@
/*
tre-internal.h - TRE internal definitions
Copyright (c) 2001-2006 Ville Laurikari <vl@iki.fi>.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <regex.h>
#include <wchar.h>
#include <wctype.h>
#define TRE_MULTIBYTE 1
#undef TRE_MBSTATE
#define TRE_WCHAR 1
#define TRE_USE_SYSTEM_WCTYPE 1
#define HAVE_WCSTOMBS 1
#define TRE_MB_CUR_MAX MB_CUR_MAX
#define NDEBUG
#define TRE_REGEX_T_FIELD __opaque
typedef int reg_errcode_t;
typedef wchar_t tre_char_t;
#ifdef TRE_DEBUG
#include <stdio.h>
#define DPRINT(msg) do {printf msg; fflush(stdout);} while(0)
#else /* !TRE_DEBUG */
#define DPRINT(msg) do { } while(0)
#endif /* !TRE_DEBUG */
#define elementsof(x) ( sizeof(x) / sizeof(x[0]) )
#if 1
int __mbtowc(wchar_t *, const char *);
#define tre_mbrtowc(pwc, s, n, ps) (__mbtowc((pwc), (s)))
#else
#define tre_mbrtowc(pwc, s, n, ps) (mbtowc((pwc), (s), (n)))
#endif
/* Wide characters. */
typedef wint_t tre_cint_t;
#define TRE_CHAR_MAX WCHAR_MAX
#ifdef TRE_MULTIBYTE
#define TRE_MB_CUR_MAX MB_CUR_MAX
#else /* !TRE_MULTIBYTE */
#define TRE_MB_CUR_MAX 1
#endif /* !TRE_MULTIBYTE */
#define tre_isalnum iswalnum
#define tre_isalpha iswalpha
#define tre_isblank iswblank
#define tre_iscntrl iswcntrl
#define tre_isdigit iswdigit
#define tre_isgraph iswgraph
#define tre_islower iswlower
#define tre_isprint iswprint
#define tre_ispunct iswpunct
#define tre_isspace iswspace
#define tre_isupper iswupper
#define tre_isxdigit iswxdigit
#define tre_tolower towlower
#define tre_toupper towupper
#define tre_strlen wcslen
/* Use system provided iswctype() and wctype(). */
typedef wctype_t tre_ctype_t;
#define tre_isctype iswctype
#define tre_ctype wctype
/* Returns number of bytes to add to (char *)ptr to make it
properly aligned for the type. */
#define ALIGN(ptr, type) \
((((long)ptr) % sizeof(type)) \
? (sizeof(type) - (((long)ptr) % sizeof(type))) \
: 0)
#undef MAX
#undef MIN
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
/* Define STRF to the correct printf formatter for strings. */
#define STRF "ls"
/* TNFA transition type. A TNFA state is an array of transitions,
the terminator is a transition with NULL `state'. */
typedef struct tnfa_transition tre_tnfa_transition_t;
struct tnfa_transition {
/* Range of accepted characters. */
tre_cint_t code_min;
tre_cint_t code_max;
/* Pointer to the destination state. */
tre_tnfa_transition_t *state;
/* ID number of the destination state. */
int state_id;
/* -1 terminated array of tags (or NULL). */
int *tags;
/* Assertion bitmap. */
int assertions;
/* Assertion parameters. */
union {
/* Character class assertion. */
tre_ctype_t class;
/* Back reference assertion. */
int backref;
} u;
/* Negative character class assertions. */
tre_ctype_t *neg_classes;
};
/* Assertions. */
#define ASSERT_AT_BOL 1 /* Beginning of line. */
#define ASSERT_AT_EOL 2 /* End of line. */
#define ASSERT_CHAR_CLASS 4 /* Character class in `class'. */
#define ASSERT_CHAR_CLASS_NEG 8 /* Character classes in `neg_classes'. */
#define ASSERT_AT_BOW 16 /* Beginning of word. */
#define ASSERT_AT_EOW 32 /* End of word. */
#define ASSERT_AT_WB 64 /* Word boundary. */
#define ASSERT_AT_WB_NEG 128 /* Not a word boundary. */
#define ASSERT_BACKREF 256 /* A back reference in `backref'. */
#define ASSERT_LAST 256
/* Tag directions. */
typedef enum {
TRE_TAG_MINIMIZE = 0,
TRE_TAG_MAXIMIZE = 1
} tre_tag_direction_t;
/* Instructions to compute submatch register values from tag values
after a successful match. */
struct tre_submatch_data {
/* Tag that gives the value for rm_so (submatch start offset). */
int so_tag;
/* Tag that gives the value for rm_eo (submatch end offset). */
int eo_tag;
/* List of submatches this submatch is contained in. */
int *parents;
};
typedef struct tre_submatch_data tre_submatch_data_t;
/* TNFA definition. */
typedef struct tnfa tre_tnfa_t;
struct tnfa {
tre_tnfa_transition_t *transitions;
unsigned int num_transitions;
tre_tnfa_transition_t *initial;
tre_tnfa_transition_t *final;
tre_submatch_data_t *submatch_data;
unsigned int num_submatches;
tre_tag_direction_t *tag_directions;
int num_tags;
int end_tag;
int num_states;
int cflags;
int have_backrefs;
};
#if 0
static int
tre_compile(regex_t *preg, const tre_char_t *regex, size_t n, int cflags);
static void
tre_free(regex_t *preg);
static void
tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
const tre_tnfa_t *tnfa, int *tags, int match_eo);
static reg_errcode_t
tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len,
tre_str_type_t type, int *match_tags, int eflags,
int *match_end_ofs);
static reg_errcode_t
tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, int len,
tre_str_type_t type, int *match_tags, int eflags,
int *match_end_ofs);
static reg_errcode_t
tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string,
int len, tre_str_type_t type, int *match_tags,
int eflags, int *match_end_ofs);
#endif
/* from tre-mem.h: */
#define TRE_MEM_BLOCK_SIZE 1024
typedef struct tre_list {
void *data;
struct tre_list *next;
} tre_list_t;
typedef struct tre_mem_struct {
tre_list_t *blocks;
tre_list_t *current;
char *ptr;
size_t n;
int failed;
void **provided;
} *tre_mem_t;
#define tre_mem_new_impl __tre_mem_new_impl
#define tre_mem_alloc_impl __tre_mem_alloc_impl
#define tre_mem_destroy __tre_mem_destroy
tre_mem_t tre_mem_new_impl(int provided, void *provided_block);
void *tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
int zero, size_t size);
/* Returns a new memory allocator or NULL if out of memory. */
#define tre_mem_new() tre_mem_new_impl(0, NULL)
/* Allocates a block of `size' bytes from `mem'. Returns a pointer to the
allocated block or NULL if an underlying malloc() failed. */
#define tre_mem_alloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 0, size)
/* Allocates a block of `size' bytes from `mem'. Returns a pointer to the
allocated block or NULL if an underlying malloc() failed. The memory
is set to zero. */
#define tre_mem_calloc(mem, size) tre_mem_alloc_impl(mem, 0, NULL, 1, size)
#ifdef TRE_USE_ALLOCA
/* alloca() versions. Like above, but memory is allocated with alloca()
instead of malloc(). */
#define tre_mem_newa() \
tre_mem_new_impl(1, alloca(sizeof(struct tre_mem_struct)))
#define tre_mem_alloca(mem, size) \
((mem)->n >= (size) \
? tre_mem_alloc_impl((mem), 1, NULL, 0, (size)) \
: tre_mem_alloc_impl((mem), 1, alloca(TRE_MEM_BLOCK_SIZE), 0, (size)))
#endif /* TRE_USE_ALLOCA */
/* Frees the memory allocator and all memory allocated with it. */
void tre_mem_destroy(tre_mem_t mem);
#define xmalloc malloc
#define xcalloc calloc
#define xfree free
#define xrealloc realloc
/* EOF */