mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-04 18:28:30 +00:00
Add x86_64-linux-gnu emulator
I wanted a tiny scriptable meltdown proof way to run userspace programs and visualize how program execution impacts memory. It helps to explain how things like Actually Portable Executable works. It can show you how the GCC generated code is going about manipulating matrices and more. I didn't feel fully comfortable with Qemu and Bochs because I'm not smart enough to understand them. I wanted something like gVisor but with much stronger levels of assurances. I wanted a single binary that'll run, on all major operating systems with an embedded GPL barrier ZIP filesystem that is tiny enough to transpile to JavaScript and run in browsers too. https://justine.storage.googleapis.com/emulator625.mp4
This commit is contained in:
parent
467504308a
commit
f4f4caab0e
1052 changed files with 65667 additions and 7825 deletions
90
third_party/regex/regcomp.c
vendored
90
third_party/regex/regcomp.c
vendored
|
@ -59,7 +59,7 @@
|
|||
#include "third_party/regex/tre.inc"
|
||||
|
||||
#define CHARCLASS_NAME_MAX 14
|
||||
#define RE_DUP_MAX 255
|
||||
#define RE_DUP_MAX 255
|
||||
|
||||
/***********************************************************************
|
||||
from tre-compile.h
|
||||
|
@ -84,16 +84,16 @@ typedef struct {
|
|||
typedef enum { LITERAL, CATENATION, ITERATION, UNION } tre_ast_type_t;
|
||||
|
||||
/* Special subtypes of TRE_LITERAL. */
|
||||
#define EMPTY -1 /* Empty leaf (denotes empty string). */
|
||||
#define EMPTY -1 /* Empty leaf (denotes empty string). */
|
||||
#define ASSERTION -2 /* Assertion leaf. */
|
||||
#define TAG -3 /* Tag leaf. */
|
||||
#define BACKREF -4 /* Back reference leaf. */
|
||||
#define TAG -3 /* Tag leaf. */
|
||||
#define BACKREF -4 /* Back reference leaf. */
|
||||
|
||||
#define IS_SPECIAL(x) ((x)->code_min < 0)
|
||||
#define IS_EMPTY(x) ((x)->code_min == EMPTY)
|
||||
#define IS_SPECIAL(x) ((x)->code_min < 0)
|
||||
#define IS_EMPTY(x) ((x)->code_min == EMPTY)
|
||||
#define IS_ASSERTION(x) ((x)->code_min == ASSERTION)
|
||||
#define IS_TAG(x) ((x)->code_min == TAG)
|
||||
#define IS_BACKREF(x) ((x)->code_min == BACKREF)
|
||||
#define IS_TAG(x) ((x)->code_min == TAG)
|
||||
#define IS_BACKREF(x) ((x)->code_min == BACKREF)
|
||||
|
||||
/* A generic AST node. All AST nodes consist of this node on the top
|
||||
level with `obj' pointing to the actual content. */
|
||||
|
@ -312,7 +312,9 @@ static void tre_stack_destroy(tre_stack_t *s) {
|
|||
free(s), s = NULL;
|
||||
}
|
||||
|
||||
static int tre_stack_num_objects(tre_stack_t *s) { return s->ptr; }
|
||||
static int tre_stack_num_objects(tre_stack_t *s) {
|
||||
return s->ptr;
|
||||
}
|
||||
|
||||
static reg_errcode_t tre_stack_push(tre_stack_t *s,
|
||||
union tre_stack_item value) {
|
||||
|
@ -348,8 +350,10 @@ static reg_errcode_t tre_stack_push(tre_stack_t *s,
|
|||
}
|
||||
|
||||
define_pushf(int, int) define_pushf(voidptr, void *)
|
||||
#define define_popf(typetag, type) \
|
||||
declare_popf(typetag, type) { return s->stack[--s->ptr].typetag##_value; }
|
||||
#define define_popf(typetag, type) \
|
||||
declare_popf(typetag, type) { \
|
||||
return s->stack[--s->ptr].typetag##_value; \
|
||||
}
|
||||
|
||||
define_popf(int, int) define_popf(voidptr, void *)
|
||||
|
||||
|
@ -383,19 +387,21 @@ define_pushf(int, int) define_pushf(voidptr, void *)
|
|||
static const struct {
|
||||
char c;
|
||||
const char *expansion;
|
||||
} tre_macros[] = {{'t', "\t"},
|
||||
{'n', "\n"},
|
||||
{'r', "\r"},
|
||||
{'f', "\f"},
|
||||
{'a', "\a"},
|
||||
{'e', "\033"},
|
||||
{'w', "[[:alnum:]_]"},
|
||||
{'W', "[^[:alnum:]_]"},
|
||||
{'s', "[[:space:]]"},
|
||||
{'S', "[^[:space:]]"},
|
||||
{'d', "[[:digit:]]"},
|
||||
{'D', "[^[:digit:]]"},
|
||||
{0, 0}};
|
||||
} tre_macros[] = {
|
||||
{'t', "\t"},
|
||||
{'n', "\n"},
|
||||
{'r', "\r"},
|
||||
{'f', "\f"},
|
||||
{'a', "\a"},
|
||||
{'e', "\033"},
|
||||
{'w', "[[:alnum:]_]"},
|
||||
{'W', "[^[:alnum:]_]"},
|
||||
{'s', "[[:space:]]"},
|
||||
{'S', "[^[:space:]]"},
|
||||
{'d', "[[:digit:]]"},
|
||||
{'D', "[^[:digit:]]"},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
/* Expands a macro delimited by `regex' and `regex_end' to `buf', which
|
||||
must have at least `len' items. Sets buf[0] to zero if the there
|
||||
|
@ -510,11 +516,13 @@ static reg_errcode_t parse_bracket_terms(tre_parse_ctx_t *ctx, const char *s,
|
|||
}
|
||||
if (*s == '-' && s != start && s[1] != ']' &&
|
||||
/* extension: [a-z--@] is accepted as [a-z]|[--@] */
|
||||
(s[1] != '-' || s[2] == ']'))
|
||||
(s[1] != '-' || s[2] == ']')) {
|
||||
return REG_ERANGE;
|
||||
if (*s == '[' && (s[1] == '.' || s[1] == '='))
|
||||
}
|
||||
if (*s == '[' && (s[1] == '.' || s[1] == '=')) {
|
||||
/* collating symbols and equivalence classes are not supported */
|
||||
return REG_ECOLLATE;
|
||||
}
|
||||
if (*s == '[' && s[1] == ':') {
|
||||
char tmp[CHARCLASS_NAME_MAX + 1];
|
||||
s += 2;
|
||||
|
@ -539,7 +547,9 @@ static reg_errcode_t parse_bracket_terms(tre_parse_ctx_t *ctx, const char *s,
|
|||
max = wc;
|
||||
/* XXX - Should use collation order instead of
|
||||
encoding values in character ranges. */
|
||||
if (len <= 0 || min > max) return REG_ERANGE;
|
||||
if (len <= 0 || min > max) {
|
||||
return REG_ERANGE;
|
||||
}
|
||||
s += len;
|
||||
}
|
||||
}
|
||||
|
@ -1523,7 +1533,7 @@ static reg_errcode_t tre_add_tags(tre_mem_t mem, tre_stack_t *stack,
|
|||
typedef enum { COPY_RECURSE, COPY_SET_RESULT_PTR } tre_copyast_symbol_t;
|
||||
|
||||
/* Flags for tre_copy_ast(). */
|
||||
#define COPY_REMOVE_TAGS 1
|
||||
#define COPY_REMOVE_TAGS 1
|
||||
#define COPY_MAXIMIZE_FIRST_TAG 2
|
||||
|
||||
static reg_errcode_t tre_copy_ast(tre_mem_t mem, tre_stack_t *stack,
|
||||
|
@ -2374,7 +2384,21 @@ static reg_errcode_t tre_ast_to_tnfa(tre_ast_node_t *node,
|
|||
if (/*CONSTCOND*/ 1) goto error_exit; \
|
||||
} while (/*CONSTCOND*/ 0)
|
||||
|
||||
int regcomp(regex_t *restrict preg, const char *restrict regex, int cflags) {
|
||||
/**
|
||||
* Compiles regular expression, e.g.
|
||||
*
|
||||
* regex_t rx;
|
||||
* EXPECT_EQ(REG_OK, regcomp(&rx, "^[A-Za-z\x7f-\uFFFF]{2}$", REG_EXTENDED));
|
||||
* EXPECT_EQ(REG_OK, regexec(&rx, "→A", 0, NULL, 0));
|
||||
* regfree(&rx);
|
||||
*
|
||||
* @param preg points to state, and needs regfree() afterwards
|
||||
* @param regex is utf-8 regular expression string
|
||||
* @param cflags can have REG_EXTENDED, REG_ICASE, REG_NEWLINE, REG_NOSUB
|
||||
* @return REG_OK, REG_NOMATCH, REG_BADPAT, etc.
|
||||
* @see regexec(), regfree(), regerror()
|
||||
*/
|
||||
int regcomp(regex_t *preg, const char *regex, int cflags) {
|
||||
tre_stack_t *stack;
|
||||
tre_ast_node_t *tree, *tmp_ast_l, *tmp_ast_r;
|
||||
tre_pos_and_tags_t *p;
|
||||
|
@ -2553,14 +2577,15 @@ error_exit:
|
|||
return errcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees any memory allocated by regcomp().
|
||||
*/
|
||||
void regfree(regex_t *preg) {
|
||||
tre_tnfa_t *tnfa;
|
||||
unsigned int i;
|
||||
tre_tnfa_transition_t *trans;
|
||||
|
||||
tnfa = (void *)preg->TRE_REGEX_T_FIELD;
|
||||
if (!tnfa) return;
|
||||
|
||||
for (i = 0; i < tnfa->num_transitions; i++)
|
||||
if (tnfa->transitions[i].state) {
|
||||
if (tnfa->transitions[i].tags)
|
||||
|
@ -2570,14 +2595,12 @@ void regfree(regex_t *preg) {
|
|||
tnfa->transitions[i].neg_classes = NULL;
|
||||
}
|
||||
if (tnfa->transitions) free(tnfa->transitions), tnfa->transitions = NULL;
|
||||
|
||||
if (tnfa->initial) {
|
||||
for (trans = tnfa->initial; trans->state; trans++) {
|
||||
if (trans->tags) free(trans->tags), trans->tags = NULL;
|
||||
}
|
||||
free(tnfa->initial), tnfa->initial = NULL;
|
||||
}
|
||||
|
||||
if (tnfa->submatch_data) {
|
||||
for (i = 0; i < tnfa->num_submatches; i++)
|
||||
if (tnfa->submatch_data[i].parents)
|
||||
|
@ -2585,7 +2608,6 @@ void regfree(regex_t *preg) {
|
|||
tnfa->submatch_data[i].parents = NULL;
|
||||
free(tnfa->submatch_data), tnfa->submatch_data = NULL;
|
||||
}
|
||||
|
||||
if (tnfa->tag_directions)
|
||||
free(tnfa->tag_directions), tnfa->tag_directions = NULL;
|
||||
if (tnfa->firstpos_chars)
|
||||
|
|
65
third_party/regex/regerror.c
vendored
65
third_party/regex/regerror.c
vendored
|
@ -1,40 +1,31 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Musl Libc │
|
||||
│ Copyright © 2005-2014 Rich Felker, et al. │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ Permission is hereby granted, free of charge, to any person obtaining │
|
||||
│ a copy of this software and associated documentation files (the │
|
||||
│ "Software"), to deal in the Software without restriction, including │
|
||||
│ without limitation the rights to use, copy, modify, merge, publish, │
|
||||
│ distribute, sublicense, and/or sell copies of the Software, and to │
|
||||
│ permit persons to whom the Software is furnished to do so, subject to │
|
||||
│ the following conditions: │
|
||||
│ │
|
||||
│ The above copyright notice and this permission notice shall be │
|
||||
│ included in all copies or substantial portions of the Software. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │
|
||||
│ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │
|
||||
│ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │
|
||||
│ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │
|
||||
│ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │
|
||||
│ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE │
|
||||
│ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
|
||||
│ This program 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "third_party/regex/tre.inc"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/regex/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 messages[] = {
|
||||
static const char kRegexErrors[] =
|
||||
"No error\0"
|
||||
"No match\0"
|
||||
"Invalid regexp\0"
|
||||
|
@ -48,14 +39,16 @@ static const char messages[] = {
|
|||
"Invalid contents of {}\0"
|
||||
"Invalid character range\0"
|
||||
"Out of memory\0"
|
||||
"Repetition not preceded by valid expression\0"
|
||||
"\0Unknown error"};
|
||||
"Repetition not preceded by valid expression\0";
|
||||
|
||||
size_t regerror(int e, const regex_t *restrict preg, char *restrict buf,
|
||||
size_t size) {
|
||||
const char *s;
|
||||
for (s = messages; e && *s; e--, s += strlen(s) + 1)
|
||||
;
|
||||
if (!*s) s++;
|
||||
return 1 + snprintf(buf, size, "%s", s);
|
||||
/**
|
||||
* Converts regular expression error code to string.
|
||||
*
|
||||
* @param e is error code
|
||||
* @return number of bytes needed to hold entire string
|
||||
*/
|
||||
size_t regerror(int e, const regex_t *preg, char *buf, size_t size) {
|
||||
return 1 + snprintf(buf, size, "%s",
|
||||
firstnonnull(indexdoublenulstring(kRegexErrors, e),
|
||||
"Unknown error"));
|
||||
}
|
||||
|
|
53
third_party/regex/regex.h
vendored
53
third_party/regex/regex.h
vendored
|
@ -10,50 +10,51 @@ COSMOPOLITAN_C_START_
|
|||
#endif
|
||||
|
||||
#define REG_EXTENDED 1
|
||||
#define REG_ICASE 2
|
||||
#define REG_NEWLINE 4
|
||||
#define REG_NOSUB 8
|
||||
#define REG_ICASE 2
|
||||
#define REG_NEWLINE 4
|
||||
#define REG_NOSUB 8
|
||||
|
||||
#define REG_NOTBOL 1
|
||||
#define REG_NOTEOL 2
|
||||
|
||||
#define REG_OK 0
|
||||
#define REG_NOMATCH 1
|
||||
#define REG_BADPAT 2
|
||||
#define REG_OK 0
|
||||
#define REG_NOMATCH 1
|
||||
#define REG_BADPAT 2
|
||||
#define REG_ECOLLATE 3
|
||||
#define REG_ECTYPE 4
|
||||
#define REG_EESCAPE 5
|
||||
#define REG_ESUBREG 6
|
||||
#define REG_EBRACK 7
|
||||
#define REG_EPAREN 8
|
||||
#define REG_EBRACE 9
|
||||
#define REG_BADBR 10
|
||||
#define REG_ERANGE 11
|
||||
#define REG_ESPACE 12
|
||||
#define REG_BADRPT 13
|
||||
#define REG_ECTYPE 4
|
||||
#define REG_EESCAPE 5
|
||||
#define REG_ESUBREG 6
|
||||
#define REG_EBRACK 7
|
||||
#define REG_EPAREN 8
|
||||
#define REG_EBRACE 9
|
||||
#define REG_BADBR 10
|
||||
#define REG_ERANGE 11
|
||||
#define REG_ESPACE 12
|
||||
#define REG_BADRPT 13
|
||||
|
||||
#define REG_ENOSYS -1
|
||||
|
||||
typedef long regoff_t;
|
||||
|
||||
typedef struct re_pattern_buffer {
|
||||
struct Regex {
|
||||
size_t re_nsub;
|
||||
void *__opaque, *__padding[4];
|
||||
size_t __nsub2;
|
||||
char __padding2;
|
||||
} regex_t;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct RegexMatch {
|
||||
regoff_t rm_so;
|
||||
regoff_t rm_eo;
|
||||
} regmatch_t;
|
||||
};
|
||||
|
||||
int regcomp(regex_t *preg, const char *regex, int flags);
|
||||
int regexec(const regex_t *preg, const char *string, size_t nmatch,
|
||||
regmatch_t pmatch[], int eflags);
|
||||
void regfree(regex_t *preg);
|
||||
size_t regerror(int errcode, const regex_t *preg, char *errbuf,
|
||||
size_t errbufsize);
|
||||
typedef struct Regex regex_t;
|
||||
typedef struct RegexMatch regmatch_t;
|
||||
|
||||
int regcomp(regex_t *, const char *, int);
|
||||
int regexec(const regex_t *, const char *, size_t, regmatch_t *, int);
|
||||
size_t regerror(int, const regex_t *, char *, size_t);
|
||||
void regfree(regex_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
6
third_party/regex/regex.mk
vendored
6
third_party/regex/regex.mk
vendored
|
@ -39,17 +39,17 @@ $(THIRD_PARTY_REGEX_A).pkg: \
|
|||
$(foreach x,$(THIRD_PARTY_REGEX_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
THIRD_PARTY_REGEX_LIBS = $(foreach x,$(THIRD_PARTY_REGEX_ARTIFACTS),$($(x)))
|
||||
THIRD_PARTY_REGEX_HDRS = $(foreach x,$(THIRD_PARTY_REGEX_ARTIFACTS),$($(x)_HDRS))
|
||||
THIRD_PARTY_REGEX_SRCS = $(foreach x,$(THIRD_PARTY_REGEX_ARTIFACTS),$($(x)_SRCS))
|
||||
THIRD_PARTY_REGEX_CHECKS = $(foreach x,$(THIRD_PARTY_REGEX_ARTIFACTS),$($(x)_CHECKS))
|
||||
THIRD_PARTY_REGEX_OBJS = $(foreach x,$(THIRD_PARTY_REGEX_ARTIFACTS),$($(x)_OBJS))
|
||||
|
||||
$(THIRD_PARTY_REGEX_OBJS): $(BUILD_FILES) third_party/regex/regex.mk
|
||||
$(THIRD_PARTY_REGEX_OBJS): third_party/regex/regex.mk
|
||||
|
||||
o/$(MODE)/third_party/regex/regcomp.o \
|
||||
o/$(MODE)/third_party/regex/regerror.o \
|
||||
o/$(MODE)/third_party/regex/regexec.o \
|
||||
o/$(MODE)/third_party/regex/tre-mem.o: \
|
||||
OVERRIDE_COPTS += \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(OLD_CODE)
|
||||
|
||||
.PHONY: o/$(MODE)/third_party/regex
|
||||
|
|
23
third_party/regex/regexec.c
vendored
23
third_party/regex/regexec.c
vendored
|
@ -469,15 +469,15 @@ typedef struct tre_backtrack_struct {
|
|||
} * tre_backtrack_t;
|
||||
|
||||
#ifdef TRE_MBSTATE
|
||||
#define BT_STACK_MBSTATE_IN stack->item.mbstate = (mbstate)
|
||||
#define BT_STACK_MBSTATE_IN stack->item.mbstate = (mbstate)
|
||||
#define BT_STACK_MBSTATE_OUT (mbstate) = stack->item.mbstate
|
||||
#else /* !TRE_MBSTATE */
|
||||
#define BT_STACK_MBSTATE_IN
|
||||
#define BT_STACK_MBSTATE_OUT
|
||||
#endif /* !TRE_MBSTATE */
|
||||
|
||||
#define tre_bt_mem_new tre_mem_new
|
||||
#define tre_bt_mem_alloc tre_mem_alloc
|
||||
#define tre_bt_mem_new tre_mem_new
|
||||
#define tre_bt_mem_alloc tre_mem_alloc
|
||||
#define tre_bt_mem_destroy tre_mem_destroy
|
||||
|
||||
#define BT_STACK_PUSH(_pos, _str_byte, _str_wide, _state, _state_id, _next_c, \
|
||||
|
@ -867,12 +867,15 @@ static void tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Wrapper functions for POSIX compatible regexp matching.
|
||||
*/
|
||||
|
||||
int regexec(const regex_t *restrict preg, const char *restrict string,
|
||||
size_t nmatch, regmatch_t pmatch[restrict], int eflags) {
|
||||
/**
|
||||
* Executes regular expression.
|
||||
*
|
||||
* @param preg is state object previously made by regcomp()
|
||||
* @param eflags can have REG_NOTBOL, REG_NOTEOL
|
||||
* @return 0 or REG_NOMATCH
|
||||
*/
|
||||
int regexec(const regex_t *preg, const char *string, size_t nmatch,
|
||||
regmatch_t pmatch[nmatch], int eflags) {
|
||||
tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD;
|
||||
reg_errcode_t status;
|
||||
regoff_t *tags = NULL, eo;
|
||||
|
@ -881,7 +884,6 @@ int regexec(const regex_t *restrict preg, const char *restrict string,
|
|||
tags = malloc(sizeof(*tags) * tnfa->num_tags);
|
||||
if (tags == NULL) return REG_ESPACE;
|
||||
}
|
||||
|
||||
/* Dispatch to the appropriate matcher. */
|
||||
if (tnfa->have_backrefs) {
|
||||
/* The regex has back references, use the backtracking matcher. */
|
||||
|
@ -890,7 +892,6 @@ int regexec(const regex_t *restrict preg, const char *restrict string,
|
|||
/* Exact matching, no back references, use the parallel matcher. */
|
||||
status = tre_tnfa_run_parallel(tnfa, string, tags, eflags, &eo);
|
||||
}
|
||||
|
||||
if (status == REG_OK) /* A match was found, so fill the submatch registers. */
|
||||
tre_fill_pmatch(nmatch, pmatch, tnfa->cflags, tnfa, tags, eo);
|
||||
if (tags) free(tags), tags = NULL;
|
||||
|
|
7
third_party/regex/tre-mem.c
vendored
7
third_party/regex/tre-mem.c
vendored
|
@ -87,7 +87,6 @@ tre_mem_t tre_mem_new_impl(int provided, void *provided_block) {
|
|||
/* 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) {
|
||||
free(l->data), l->data = NULL;
|
||||
tmp = l->next;
|
||||
|
@ -101,11 +100,9 @@ void tre_mem_destroy(tre_mem_t mem) {
|
|||
void *tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
|
||||
int zero, size_t size) {
|
||||
void *ptr;
|
||||
|
||||
if (mem->failed) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mem->n < size) {
|
||||
/* We need more memory than is available in the current block.
|
||||
Allocate a new block. */
|
||||
|
@ -142,17 +139,13 @@ void *tre_mem_alloc_impl(tre_mem_t mem, int provided, void *provided_block,
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue