| 1629 | } |
| 1630 | |
| 1631 | static const char *lexical_binding_key(CBMExtractCtx *ctx, WalkState *state, const char *name) { |
| 1632 | if (!ctx || !name) { |
| 1633 | return name; |
| 1634 | } |
| 1635 | /* Preserve language namespaces: Perl sigils and Vim prefixes distinguish |
| 1636 | * different variables. Tcl's grammar is asymmetric (`name` versus |
| 1637 | * `$name`), so unwrap only that language-defined reference sigil. */ |
| 1638 | if (ctx->language == CBM_LANG_TCL && name[0] == '$') { |
| 1639 | name++; |
| 1640 | } |
| 1641 | if (!lexical_identifier_case_insensitive(ctx->language)) { |
| 1642 | return name; |
| 1643 | } |
| 1644 | size_t n = strlen(name); |
| 1645 | char *folded = (char *)cbm_arena_alloc(ctx->arena, n + 1U); |
| 1646 | if (!folded) { |
| 1647 | if (state) { |
| 1648 | state->lexical_binding_tracking_failed = true; |
| 1649 | } |
| 1650 | return NULL; |
| 1651 | } |
| 1652 | for (size_t i = 0; i < n; i++) { |
| 1653 | folded[i] = (char)tolower((unsigned char)name[i]); |
| 1654 | } |
| 1655 | folded[n] = '\0'; |
| 1656 | return folded; |
| 1657 | } |
| 1658 | |
| 1659 | static void stamp_usage_site(CBMExtractCtx *ctx, CBMUsage *usage, TSNode node, const char *name, |
| 1660 | WalkState *state) { |
no test coverage detected