Files
Hermit/vendor/tre-regex/tre.h
T
WHC 2a43ae6622
ci / linux (clang) (push) Canceled after 0s
ci / linux (gcc) (push) Canceled after 0s
ci / sanitizers (push) Canceled after 0s
ci / musl (push) Canceled after 0s
ci / macos (push) Canceled after 0s
Windows: official port -- UCRT static build, UTF-8 throughout, Low IL sandbox, ncurses TUI, installer; v0.6.0
Build
  * cross build switches to pkgsCross.ucrt64 (shell-win.nix); curl (Schannel),
    winpthreads and ncurses 6.6 are linked statically, so the release is
    cst-agent.exe + busybox.exe (busybox-w32 Unicode) with no extra DLLs
  * windres embeds a manifest with activeCodePage=UTF-8 and a version resource
  * ncurses 6.6 Windows console driver patches (mouse button state, A_DIM,
    wide-char declarations): scripts/patches/
  * scripts/bootstrap_msys2.sh builds the same release natively in MSYS2
    UCRT64; PR #1's MINGW64 notes now point there
  * vendor/tre-regex (musl's TRE) provides <regex.h> on MinGW

UTF-8
  * paths cross the system call boundary as UTF-16 (*W APIs); console code
    pages set to 65001 and restored on exit; files are read and written in
    binary mode
  * child output that is not valid UTF-8 is decoded from the console, OEM or
    ANSI system code page
  * read_file hides CR; edit_file, apply_patch and write_file keep CRLF line
    endings and a UTF-8 BOM

OS layer and processes
  * os_dir_* and cst_fnmatch replace the POSIX-only directory walks in
    subagent, plugins, skills, undo and fs_tools; realpath / path_under and
    symlink rejection work on Windows
  * every child goes through CreateProcessW with its own environment block
    inside a Job Object, so timeouts and Esc end the whole process tree

Sandbox (auto mode, "auto · lowil")
  * run_shell runs with a restricted Low integrity token; the workspace gets
    an inheritable Low label once, the sandbox TEMP is labeled Low, and the
    credentials file gets a no-read-up label
  * drive roots, the profile and system folders are never labeled
  * network commands still ask, since Low IL does not block the network;
    Access denied and MSYS2's 0xc0000142 offer a rerun outside the sandbox
  * /sandbox lists labeled folders, /sandbox reset-labels restores them

TUI
  * raster console fonts are switched to Consolas / NSimSun while running
  * the home logo falls back to text when the console font lacks U+2580
  * mouse drag copy goes to the Windows clipboard

Distribution
  * scripts/install_windows.ps1 installs a Gitea release into
    %LOCALAPPDATA%\Programs\cst-agent and adds it to the user PATH;
    cst-agent-update.cmd reruns it; scripts/release_windows.sh uploads the
    zip with the token taken from the environment
  * scripts/run_windows.bat is gone; docs/README-windows.md is rewritten

Tests
  * new test_lowil, test_win_utf8 and test_os_dir; tests made portable
    (cst_test_util.h)
  * scripts/win_test.sh and scripts/winvm/ run the suite on English and
    Chinese Windows Server VMs as Administrator, a standard user and a
    Chinese user name: 29/29 on all six
2026-10-06 23:08:14 +08:00

268 lines
8.4 KiB
C

/*
tre-internal.h - TRE internal definitions
Copyright (c) 2001-2009 Ville Laurikari <vl@iki.fi>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "regex.h"
#include <stdint.h>
#include <wchar.h>
#include <wctype.h>
#define hidden
#undef TRE_MBSTATE
#ifndef NDEBUG
#define NDEBUG
#endif
#ifndef CHARCLASS_NAME_MAX
#define CHARCLASS_NAME_MAX 14
#endif
#ifndef RE_DUP_MAX
#define RE_DUP_MAX 255
#endif
#define TRE_REGEX_T_FIELD __opaque
typedef int reg_errcode_t;
typedef int tre_char_t;
#define DPRINT(msg) do { } while(0)
#define elementsof(x) ( sizeof(x) / sizeof(x[0]) )
/* wchar_t is 16 bits on Windows: decode UTF-8 to code points ourselves.
Returns the sequence length, 0 at NUL, -1 on invalid input. */
static inline int tre_mbtowc(tre_char_t *pwc, const char *s, size_t n)
{
const unsigned char *p = (const unsigned char *)s;
int c, len, i;
if (n == 0) return -1;
c = p[0];
if (c < 0x80) { *pwc = c; return c ? 1 : 0; }
if (c < 0xC2) return -1;
if (c < 0xE0) { len = 2; c &= 0x1F; }
else if (c < 0xF0) { len = 3; c &= 0x0F; }
else if (c < 0xF5) { len = 4; c &= 0x07; }
else return -1;
if ((size_t)len > n) return -1;
for (i = 1; i < len; i++) {
if ((p[i] & 0xC0) != 0x80) return -1;
c = (c << 6) | (p[i] & 0x3F);
}
if ((len == 3 && c < 0x800) || (len == 4 && (c < 0x10000 || c > 0x10FFFF))
|| (c >= 0xD800 && c <= 0xDFFF)) return -1;
*pwc = c;
return len;
}
#define tre_mbrtowc(pwc, s, n, ps) (tre_mbtowc((pwc), (s), (n)))
/* Wide characters. */
typedef int tre_cint_t;
#define TRE_CHAR_MAX 0x10ffff
#define tre_isalnum(c) ((c) <= 0xFFFF ? iswalnum((wint_t)(c)) : 1)
#define tre_isalpha(c) ((c) <= 0xFFFF ? iswalpha((wint_t)(c)) : 1)
#define tre_isblank(c) ((c) <= 0xFFFF ? iswblank((wint_t)(c)) : 0)
#define tre_iscntrl(c) ((c) <= 0xFFFF ? iswcntrl((wint_t)(c)) : 0)
#define tre_isdigit(c) ((c) <= 0xFFFF ? iswdigit((wint_t)(c)) : 0)
#define tre_isgraph(c) ((c) <= 0xFFFF ? iswgraph((wint_t)(c)) : 1)
#define tre_islower(c) ((c) <= 0xFFFF ? iswlower((wint_t)(c)) : 0)
#define tre_isprint(c) ((c) <= 0xFFFF ? iswprint((wint_t)(c)) : 1)
#define tre_ispunct(c) ((c) <= 0xFFFF ? iswpunct((wint_t)(c)) : 0)
#define tre_isspace(c) ((c) <= 0xFFFF ? iswspace((wint_t)(c)) : 0)
#define tre_isupper(c) ((c) <= 0xFFFF ? iswupper((wint_t)(c)) : 0)
#define tre_isxdigit(c) ((c) <= 0xFFFF ? iswxdigit((wint_t)(c)) : 0)
#define tre_tolower(c) ((c) <= 0xFFFF ? (int)towlower((wint_t)(c)) : (c))
#define tre_toupper(c) ((c) <= 0xFFFF ? (int)towupper((wint_t)(c)) : (c))
#define tre_strlen wcslen
/* Use system provided iswctype() and wctype(). */
typedef wctype_t tre_ctype_t;
#define tre_isctype(c, t) ((c) <= 0xFFFF ? iswctype((wint_t)(c), (t)) : 0)
#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) \
((((uintptr_t)ptr) % sizeof(type)) \
? (sizeof(type) - (((uintptr_t)ptr) % sizeof(type))) \
: 0)
#undef MAX
#undef MIN
#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))
/* 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;
char *firstpos_chars;
int first_char;
unsigned int num_submatches;
tre_tag_direction_t *tag_directions;
int *minimal_tags;
int num_tags;
int num_minimals;
int end_tag;
int num_states;
int cflags;
int have_backrefs;
int have_approx;
};
/* 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
hidden tre_mem_t tre_mem_new_impl(int provided, void *provided_block);
hidden 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. */
hidden void tre_mem_destroy(tre_mem_t mem);
#define xmalloc malloc
#define xcalloc calloc
#define xfree free
#define xrealloc realloc