tree-sitter-language-pack 1.14.1

Core library for tree-sitter language pack - provides compiled parsers for 371 languages
/*
 * ts-pack deterministic wide-ctype shim.
 *
 * ~keep Vendored grammar scanners call the libc wide-ctype classifiers
 * (iswalpha/iswalnum/iswspace/...) on Unicode code points. Those functions are
 * locale-sensitive and, for non-ASCII code points, disagree between BSD libc
 * (macOS) and glibc (Linux) even under the same locale name — e.g.
 * iswspace(U+00A0) and iswalpha(U+0670) differ across platforms. That makes the
 * per-platform parser .so/.dylib artifacts tokenize the same source into
 * different parse trees, which is a cross-platform non-determinism bug for any
 * consumer that reindents/formats from the tree.
 *
 * This header is force-included (clang/gcc `-include`, MSVC `/FI`) ahead of
 * every scanner translation unit. It redirects the libc entry points to small
 * wrappers backed by utf8proc's frozen, in-source Unicode tables, so the result
 * is identical on every platform *by construction* (same source, no libc, no
 * locale) while preserving non-ASCII Unicode correctness.
 *
 * Conflict-safety: the real libc declarations are pulled in FIRST (below), so
 * their prototypes are emitted under the real names before any redirect macro
 * exists; a scanner's own later `#include <wctype.h>`/`<cwctype>` then hits the
 * include guard and is a no-op — no prototype/macro clash. The redirects are
 * *function-like* macros, so a C++ `using std::iswspace;` (identifier not
 * followed by `(`) is left untouched and only call sites expand.
 */
#ifndef TS_PACK_CTYPE_SHIM_H
#define TS_PACK_CTYPE_SHIM_H

/* ~keep Emit the real libc prototypes under their real names before
 * redirecting. Only <wctype.h>/<cwctype> — deliberately NOT <wchar.h>, which
 * transitively leaks <stdio.h>'s EOF macro and breaks scanners that use EOF as
 * an identifier (e.g. caddy's `enum { EOF }`). <wctype.h> alone supplies wint_t
 * + prototypes. */
#ifdef __cplusplus
#include <cwctype>
#else
#include <wctype.h>
#endif

#include "utf8proc.h"

/* ~keep Unicode range guard: utf8proc classifies out-of-range as unassigned. */
#define TS_PACK_CP_MAX 0x10FFFF

static inline int ts_pack__cat(utf8proc_int32_t c) {
  if (c < 0 || c > TS_PACK_CP_MAX) {
    return UTF8PROC_CATEGORY_CN;
  }
  return (int)utf8proc_category(c);
}

static inline int ts_pack_iswalpha(utf8proc_int32_t c) {
  switch (ts_pack__cat(c)) {
  case UTF8PROC_CATEGORY_LU:
  case UTF8PROC_CATEGORY_LL:
  case UTF8PROC_CATEGORY_LT:
  case UTF8PROC_CATEGORY_LM:
  case UTF8PROC_CATEGORY_LO:
    return 1;
  default:
    return 0;
  }
}

/* ~keep iswdigit/iswxdigit are ASCII-only by the C standard (locale-invariant),
 * so a fixed ASCII test both matches every libc and stays deterministic. */
static inline int ts_pack_iswdigit(utf8proc_int32_t c) {
  return c >= '0' && c <= '9';
}

static inline int ts_pack_iswxdigit(utf8proc_int32_t c) {
  return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
         (c >= 'A' && c <= 'F');
}

/* ~keep alnum keeps Unicode identifier continuation working: letters plus all
 * numeric categories (decimal, letter-number, other-number). */
static inline int ts_pack_iswalnum(utf8proc_int32_t c) {
  switch (ts_pack__cat(c)) {
  case UTF8PROC_CATEGORY_LU:
  case UTF8PROC_CATEGORY_LL:
  case UTF8PROC_CATEGORY_LT:
  case UTF8PROC_CATEGORY_LM:
  case UTF8PROC_CATEGORY_LO:
  case UTF8PROC_CATEGORY_ND:
  case UTF8PROC_CATEGORY_NL:
  case UTF8PROC_CATEGORY_NO:
    return 1;
  default:
    return 0;
  }
}

/* ~keep Frozen Unicode White_Space property set (identical on every platform).
 */
static inline int ts_pack_iswspace(utf8proc_int32_t c) {
  switch (c) {
  case 0x09:
  case 0x0A:
  case 0x0B:
  case 0x0C:
  case 0x0D:
  case 0x20:
  case 0x85:
  case 0xA0:
  case 0x1680:
  case 0x2000:
  case 0x2001:
  case 0x2002:
  case 0x2003:
  case 0x2004:
  case 0x2005:
  case 0x2006:
  case 0x2007:
  case 0x2008:
  case 0x2009:
  case 0x200A:
  case 0x2028:
  case 0x2029:
  case 0x202F:
  case 0x205F:
  case 0x3000:
    return 1;
  default:
    return 0;
  }
}

static inline int ts_pack_iswupper(utf8proc_int32_t c) {
  return ts_pack__cat(c) == UTF8PROC_CATEGORY_LU;
}

static inline int ts_pack_iswlower(utf8proc_int32_t c) {
  return ts_pack__cat(c) == UTF8PROC_CATEGORY_LL;
}

static inline int ts_pack_iswpunct(utf8proc_int32_t c) {
  switch (ts_pack__cat(c)) {
  case UTF8PROC_CATEGORY_PC:
  case UTF8PROC_CATEGORY_PD:
  case UTF8PROC_CATEGORY_PS:
  case UTF8PROC_CATEGORY_PE:
  case UTF8PROC_CATEGORY_PI:
  case UTF8PROC_CATEGORY_PF:
  case UTF8PROC_CATEGORY_PO:
  case UTF8PROC_CATEGORY_SM:
  case UTF8PROC_CATEGORY_SC:
  case UTF8PROC_CATEGORY_SK:
  case UTF8PROC_CATEGORY_SO:
    return 1;
  default:
    return 0;
  }
}

static inline int ts_pack_iswcntrl(utf8proc_int32_t c) {
  return ts_pack__cat(c) == UTF8PROC_CATEGORY_CC;
}

static inline int ts_pack_iswblank(utf8proc_int32_t c) {
  return c == '\t' || ts_pack__cat(c) == UTF8PROC_CATEGORY_ZS;
}

static inline int ts_pack_iswprint(utf8proc_int32_t c) {
  switch (ts_pack__cat(c)) {
  case UTF8PROC_CATEGORY_CC:
  case UTF8PROC_CATEGORY_CF:
  case UTF8PROC_CATEGORY_CS:
  case UTF8PROC_CATEGORY_CN:
    return 0;
  default:
    return 1;
  }
}

static inline int ts_pack_iswgraph(utf8proc_int32_t c) {
  return ts_pack_iswprint(c) && !ts_pack_iswspace(c);
}

static inline utf8proc_int32_t ts_pack_towupper(utf8proc_int32_t c) {
  if (c < 0 || c > TS_PACK_CP_MAX) {
    return c;
  }
  return utf8proc_toupper(c);
}

static inline utf8proc_int32_t ts_pack_towlower(utf8proc_int32_t c) {
  if (c < 0 || c > TS_PACK_CP_MAX) {
    return c;
  }
  return utf8proc_tolower(c);
}

/*
 * ~keep Function-like redirects. Defined AFTER the real prototypes so there is
 * no clash. iswblank is redirected for C only: the sole C++ user (norg) calls
 * it as `std::iswblank(...)`, and a macro would rewrite that to a non-existent
 * `std::ts_pack_iswblank` — leaving it on libc there is harmless (blank is
 * near-ASCII) and keeps that translation unit compiling.
 */
#define iswalpha(c) ts_pack_iswalpha((c))
#define iswalnum(c) ts_pack_iswalnum((c))
#define iswdigit(c) ts_pack_iswdigit((c))
#define iswxdigit(c) ts_pack_iswxdigit((c))
#define iswspace(c) ts_pack_iswspace((c))
#define iswupper(c) ts_pack_iswupper((c))
#define iswlower(c) ts_pack_iswlower((c))
#define iswpunct(c) ts_pack_iswpunct((c))
#define iswcntrl(c) ts_pack_iswcntrl((c))
#define iswprint(c) ts_pack_iswprint((c))
#define iswgraph(c) ts_pack_iswgraph((c))
#define towupper(c) ts_pack_towupper((c))
#define towlower(c) ts_pack_towlower((c))
#ifndef __cplusplus
#define iswblank(c) ts_pack_iswblank((c))
#endif

#endif /* TS_PACK_CTYPE_SHIM_H */