From 061fa5e3917eeb12b439c7cd1ce90d3573a02da0 Mon Sep 17 00:00:00 2001 From: librelad Date: Wed, 27 May 2026 00:10:35 +0100 Subject: [PATCH] fix(lazy-load): count both braces per line so embedded awk doesn't strand the depth tracker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `webuiSystemUpdate` was calling `webuiSystemMetrics` and getting "command not found": the lazy-load manifest was missing it (and `webuiSystemApps`), even though both are defined in webui_system_metrics.sh. Cause: the manifest scanner's awk-based depth tracker is line-based. The first function in that file, `_metricsReadCpu`, contains an embedded awk script: _metricsReadCpu() { awk '/^cpu /{ <-- the open brace runs to end-of-line, depth += 1 ... }' /proc/stat <-- the close brace is mid-line, NOT counted } <-- depth-- but we started one too high The increment rule fired for the `/^cpu /{` line (open brace at EOL), the matching close on the `}' /proc/stat` line was not counted because the existing depth>0 branch only decremented when stripped was EXACTLY `}`. Result: depth ended at 1 instead of 0 after _metricsReadCpu, and every subsequent funcname() header was treated as "still inside a function" and silently dropped. Same pattern across the ~6 files the lazy-loader memory called out as "false-positive eager". Fix: in the depth>0 branch, count open AND close braces per line symmetrically and apply the net delta. Drops the redundant "exactly `}`" special-case rule, clamps depth at 0 as a sanity backstop. False positives from braces inside string literals could under/over-count locally, but the clamp + the next legitimate `funcname()` header at depth-0 re-anchors the tracker. Result on a full regen: - 858 → 876 functions indexed (+18 previously-stranded) - webuiSystemMetrics + webuiSystemApps now correctly autoloaded - eager-file count: 9 → 11 (two files that genuinely have both function defs and top-level side effects are now correctly seen both as eager AND get their functions indexed — net win on every axis) Verified live: the WebUI updater that was failing with "command not found" now prints "Updated system information..." cleanly. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- .../source/files/arrays/function_manifest.sh | 60 ++++++++++++++++++- .../files/generate_function_manifest.sh | 29 +++++---- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/scripts/source/files/arrays/function_manifest.sh b/scripts/source/files/arrays/function_manifest.sh index eda9c02..c56ec47 100644 --- a/scripts/source/files/arrays/function_manifest.sh +++ b/scripts/source/files/arrays/function_manifest.sh @@ -112,7 +112,9 @@ declare -gA LP_FN_MAP=( [authAdapter_focalboard_setAdmin]="focalboard/scripts/focalboard_auth.sh" [authAdapter_focalboard_setPassword]="focalboard/scripts/focalboard_auth.sh" [authAdapter_gitea_createUser]="gitea/scripts/gitea_auth.sh" + [authAdapter_gitea_deleteUser]="gitea/scripts/gitea_auth.sh" [authAdapter_gitea_listUsers]="gitea/scripts/gitea_auth.sh" + [authAdapter_gitea_setAdmin]="gitea/scripts/gitea_auth.sh" [authAdapter_gitea_setPassword]="gitea/scripts/gitea_auth.sh" [authAdapter_invidious_createUser]="invidious/scripts/invidious_auth.sh" [authAdapter_invidious_deleteUser]="invidious/scripts/invidious_auth.sh" @@ -195,7 +197,10 @@ declare -gA LP_FN_MAP=( [borgLocationUri]="backup/engine/borg_env.sh" [borgRestoreSnapshot]="backup/engine/borg_restore.sh" [borgRestoreSystemLatest]="backup/engine/borg_restore.sh" + [borgSnapshotLatestId]="backup/engine/borg_snapshots.sh" + [borgSnapshotListFiles]="backup/engine/borg_snapshots.sh" [borgSnapshotsJson]="backup/engine/borg_snapshots.sh" + [borgSystemSnapshotsJson]="backup/engine/borg_snapshots.sh" [changeRootOwnedFile]="function/permission/ownership/root_file.sh" [changeUserGroupOnFolder]="function/permission/ownership/folder_group.sh" [checkApplicationsConfigFilesMissingVariables]="config/application/application_missing_variables.sh" @@ -447,6 +452,7 @@ declare -gA LP_FN_MAP=( [installBookstack]="bookstack/bookstack.sh" [installCrontab]="crontab/crontab_install.sh" [installCrowdsec]="crowdsec/crowdsec.sh" + [installCrowdsecHost]="crowdsec/scripts/crowdsec_install_host.sh" [installDashy]="dashy/dashy.sh" [installDebianUbuntu]="os/install/ubuntu.sh" [installDockerNetwork]="docker/network/network_setup.sh" @@ -533,7 +539,11 @@ declare -gA LP_FN_MAP=( [kopiaLocationStats]="backup/engine/kopia_check.sh" [kopiaLocationUri]="backup/engine/kopia_env.sh" [kopiaRestoreSnapshot]="backup/engine/kopia_restore.sh" + [kopiaRestoreSystemLatest]="backup/engine/kopia_snapshots.sh" + [kopiaSnapshotLatestId]="backup/engine/kopia_snapshots.sh" + [kopiaSnapshotListFiles]="backup/engine/kopia_snapshots.sh" [kopiaSnapshotsJson]="backup/engine/kopia_snapshots.sh" + [kopiaSystemSnapshotsJson]="backup/engine/kopia_snapshots.sh" [_linkdingManage]="linkding/scripts/linkding_auth.sh" [listDockerComposeFiles]="config/docker/docker_list_compose_files.sh" [localDnsAppHosts]="network/dns/setup_local_dns.sh" @@ -596,6 +606,10 @@ declare -gA LP_FN_MAP=( [monitoringAppEnabled]="network/monitoring/monitoring.sh" [monitoringInstalledApps]="network/monitoring/monitoring.sh" [monitoringIsInstalled]="network/monitoring/monitoring.sh" + [monitoringRefreshAll]="network/monitoring/monitoring.sh" + [monitoringRefreshGrafana]="network/monitoring/monitoring.sh" + [monitoringRefreshPrometheus]="network/monitoring/monitoring.sh" + [monitoringResolveScrapeTags]="network/monitoring/monitoring.sh" [monitoringToggleAppConfig]="network/monitoring/monitoring.sh" [moveFile]="function/file/move_file.sh" [_nextcloudOcc]="nextcloud/scripts/nextcloud_auth.sh" @@ -655,6 +669,7 @@ declare -gA LP_FN_MAP=( [reconcileConfigFile]="config/core/variables/config_scan_variables.sh" [reconcileContainersTopOwnership]="function/permission/libreportal_folders.sh" [reconcileDockerOwnership]="function/permission/libreportal_folders.sh" + [_reconcileSplitValueComment]="config/core/variables/config_scan_variables.sh" [reconcileWebuiDirOwnership]="function/permission/libreportal_folders.sh" [recoverOrphans]="crontab/task/crontab_task_processor.sh" [removeEmptyLineAtFileEnd]="function/file/empty_line/remove_line.sh" @@ -753,6 +768,7 @@ declare -gA LP_FN_MAP=( [setupHeadscaleRemote]="headscale/scripts/headscale_setup_remote.sh" [setupHeadscaleUser]="headscale/scripts/headscale_user.sh" [setupHeadscaleVariables]="network/variables/headscale_variables.sh" + [setupLocalDnsRewrites]="network/dns/setup_local_dns.sh" [setupTaskDir]="crontab/task/crontab_task_processor.sh" [setupWizardMarkComplete]="setup/setup_lock.sh" [setupWizardReset]="setup/setup_lock.sh" @@ -857,9 +873,11 @@ declare -gA LP_FN_MAP=( [webuiSetConfigOptions]="webui/data/generators/config/webui_cli_config_set.sh" [webuiSyncAppIcon]="webui/data/utils/webui_app_icons.sh" [webuiSyncAppIcons]="webui/data/utils/webui_app_icons.sh" + [webuiSystemApps]="webui/data/generators/system/webui_system_metrics.sh" [webuiSystemDisk]="webui/data/generators/system/webui_system_disk.sh" [webuiSystemInfo]="webui/data/generators/system/webui_system_info.sh" [webuiSystemMemory]="webui/data/generators/system/webui_system_memory.sh" + [webuiSystemMetrics]="webui/data/generators/system/webui_system_metrics.sh" [webuiSystemUpdate]="webui/data/generators/system/webui_system_update.sh" [webuiSystemUpdateCheck]="webui/data/generators/system/webui_system_update.sh" [webuiUpdateAppLog]="webui/data/utils/webui_app_log.sh" @@ -975,7 +993,9 @@ declare -gA LP_FN_ROOT=( [authAdapter_focalboard_setAdmin]="containers" [authAdapter_focalboard_setPassword]="containers" [authAdapter_gitea_createUser]="containers" + [authAdapter_gitea_deleteUser]="containers" [authAdapter_gitea_listUsers]="containers" + [authAdapter_gitea_setAdmin]="containers" [authAdapter_gitea_setPassword]="containers" [authAdapter_invidious_createUser]="containers" [authAdapter_invidious_deleteUser]="containers" @@ -1058,7 +1078,10 @@ declare -gA LP_FN_ROOT=( [borgLocationUri]="scripts" [borgRestoreSnapshot]="scripts" [borgRestoreSystemLatest]="scripts" + [borgSnapshotLatestId]="scripts" + [borgSnapshotListFiles]="scripts" [borgSnapshotsJson]="scripts" + [borgSystemSnapshotsJson]="scripts" [changeRootOwnedFile]="scripts" [changeUserGroupOnFolder]="scripts" [checkApplicationsConfigFilesMissingVariables]="scripts" @@ -1310,6 +1333,7 @@ declare -gA LP_FN_ROOT=( [installBookstack]="containers" [installCrontab]="scripts" [installCrowdsec]="containers" + [installCrowdsecHost]="containers" [installDashy]="containers" [installDebianUbuntu]="scripts" [installDockerNetwork]="scripts" @@ -1396,7 +1420,11 @@ declare -gA LP_FN_ROOT=( [kopiaLocationStats]="scripts" [kopiaLocationUri]="scripts" [kopiaRestoreSnapshot]="scripts" + [kopiaRestoreSystemLatest]="scripts" + [kopiaSnapshotLatestId]="scripts" + [kopiaSnapshotListFiles]="scripts" [kopiaSnapshotsJson]="scripts" + [kopiaSystemSnapshotsJson]="scripts" [_linkdingManage]="containers" [listDockerComposeFiles]="scripts" [localDnsAppHosts]="scripts" @@ -1459,6 +1487,10 @@ declare -gA LP_FN_ROOT=( [monitoringAppEnabled]="scripts" [monitoringInstalledApps]="scripts" [monitoringIsInstalled]="scripts" + [monitoringRefreshAll]="scripts" + [monitoringRefreshGrafana]="scripts" + [monitoringRefreshPrometheus]="scripts" + [monitoringResolveScrapeTags]="scripts" [monitoringToggleAppConfig]="scripts" [moveFile]="scripts" [_nextcloudOcc]="containers" @@ -1518,6 +1550,7 @@ declare -gA LP_FN_ROOT=( [reconcileConfigFile]="scripts" [reconcileContainersTopOwnership]="scripts" [reconcileDockerOwnership]="scripts" + [_reconcileSplitValueComment]="scripts" [reconcileWebuiDirOwnership]="scripts" [recoverOrphans]="scripts" [removeEmptyLineAtFileEnd]="scripts" @@ -1616,6 +1649,7 @@ declare -gA LP_FN_ROOT=( [setupHeadscaleRemote]="containers" [setupHeadscaleUser]="containers" [setupHeadscaleVariables]="scripts" + [setupLocalDnsRewrites]="scripts" [setupTaskDir]="scripts" [setupWizardMarkComplete]="scripts" [setupWizardReset]="scripts" @@ -1720,9 +1754,11 @@ declare -gA LP_FN_ROOT=( [webuiSetConfigOptions]="scripts" [webuiSyncAppIcon]="scripts" [webuiSyncAppIcons]="scripts" + [webuiSystemApps]="scripts" [webuiSystemDisk]="scripts" [webuiSystemInfo]="scripts" [webuiSystemMemory]="scripts" + [webuiSystemMetrics]="scripts" [webuiSystemUpdate]="scripts" [webuiSystemUpdateCheck]="scripts" [webuiUpdateAppLog]="scripts" @@ -1742,13 +1778,15 @@ declare -gA LP_FN_ROOT=( LP_EAGER_FILES=( "scripts:backup/db/backup_db.sh" "scripts:backup/files/backup_files.sh" - "scripts:cli/commands/debug/cli_debug_commands.sh" "scripts:crontab/task/crontab_check_processor.sh" "scripts:crontab/task/crontab_task_processor.sh" + "scripts:docker/install/rootless/rootless_apparmor.sh" "scripts:docker/type_switcher/swap_docker_type.sh" - "containers:gluetun/scripts/gluetun_providers.sh" "scripts:migrate/migrate_url_rewrite.sh" "scripts:setup/setup_lock.sh" + "scripts:webui/data/generators/apps/webui_config.sh" + "scripts:webui/data/generators/apps/webui_services.sh" + "scripts:webui/data/generators/categories/webui_create_app_field_mappings.sh" ) # Autoload stubs — one per public function. First call sources the @@ -1856,7 +1894,9 @@ authAdapter_focalboard_listUsers() { source "${install_containers_dir}focalboard authAdapter_focalboard_setAdmin() { source "${install_containers_dir}focalboard/scripts/focalboard_auth.sh"; authAdapter_focalboard_setAdmin "$@"; } authAdapter_focalboard_setPassword() { source "${install_containers_dir}focalboard/scripts/focalboard_auth.sh"; authAdapter_focalboard_setPassword "$@"; } authAdapter_gitea_createUser() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; authAdapter_gitea_createUser "$@"; } +authAdapter_gitea_deleteUser() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; authAdapter_gitea_deleteUser "$@"; } authAdapter_gitea_listUsers() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; authAdapter_gitea_listUsers "$@"; } +authAdapter_gitea_setAdmin() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; authAdapter_gitea_setAdmin "$@"; } authAdapter_gitea_setPassword() { source "${install_containers_dir}gitea/scripts/gitea_auth.sh"; authAdapter_gitea_setPassword "$@"; } authAdapter_invidious_createUser() { source "${install_containers_dir}invidious/scripts/invidious_auth.sh"; authAdapter_invidious_createUser "$@"; } authAdapter_invidious_deleteUser() { source "${install_containers_dir}invidious/scripts/invidious_auth.sh"; authAdapter_invidious_deleteUser "$@"; } @@ -1939,7 +1979,10 @@ borgLocationStats() { source "${install_scripts_dir}backup/engine/borg_check.sh" borgLocationUri() { source "${install_scripts_dir}backup/engine/borg_env.sh"; borgLocationUri "$@"; } borgRestoreSnapshot() { source "${install_scripts_dir}backup/engine/borg_restore.sh"; borgRestoreSnapshot "$@"; } borgRestoreSystemLatest() { source "${install_scripts_dir}backup/engine/borg_restore.sh"; borgRestoreSystemLatest "$@"; } +borgSnapshotLatestId() { source "${install_scripts_dir}backup/engine/borg_snapshots.sh"; borgSnapshotLatestId "$@"; } +borgSnapshotListFiles() { source "${install_scripts_dir}backup/engine/borg_snapshots.sh"; borgSnapshotListFiles "$@"; } borgSnapshotsJson() { source "${install_scripts_dir}backup/engine/borg_snapshots.sh"; borgSnapshotsJson "$@"; } +borgSystemSnapshotsJson() { source "${install_scripts_dir}backup/engine/borg_snapshots.sh"; borgSystemSnapshotsJson "$@"; } changeRootOwnedFile() { source "${install_scripts_dir}function/permission/ownership/root_file.sh"; changeRootOwnedFile "$@"; } changeUserGroupOnFolder() { source "${install_scripts_dir}function/permission/ownership/folder_group.sh"; changeUserGroupOnFolder "$@"; } checkApplicationsConfigFilesMissingVariables() { source "${install_scripts_dir}config/application/application_missing_variables.sh"; checkApplicationsConfigFilesMissingVariables "$@"; } @@ -2191,6 +2234,7 @@ installAuthelia() { source "${install_containers_dir}authelia/authelia.sh"; inst installBookstack() { source "${install_containers_dir}bookstack/bookstack.sh"; installBookstack "$@"; } installCrontab() { source "${install_scripts_dir}crontab/crontab_install.sh"; installCrontab "$@"; } installCrowdsec() { source "${install_containers_dir}crowdsec/crowdsec.sh"; installCrowdsec "$@"; } +installCrowdsecHost() { source "${install_containers_dir}crowdsec/scripts/crowdsec_install_host.sh"; installCrowdsecHost "$@"; } installDashy() { source "${install_containers_dir}dashy/dashy.sh"; installDashy "$@"; } installDebianUbuntu() { source "${install_scripts_dir}os/install/ubuntu.sh"; installDebianUbuntu "$@"; } installDockerNetwork() { source "${install_scripts_dir}docker/network/network_setup.sh"; installDockerNetwork "$@"; } @@ -2277,7 +2321,11 @@ kopiaInstall() { source "${install_scripts_dir}backup/engine/kopia_install.sh"; kopiaLocationStats() { source "${install_scripts_dir}backup/engine/kopia_check.sh"; kopiaLocationStats "$@"; } kopiaLocationUri() { source "${install_scripts_dir}backup/engine/kopia_env.sh"; kopiaLocationUri "$@"; } kopiaRestoreSnapshot() { source "${install_scripts_dir}backup/engine/kopia_restore.sh"; kopiaRestoreSnapshot "$@"; } +kopiaRestoreSystemLatest() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaRestoreSystemLatest "$@"; } +kopiaSnapshotLatestId() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSnapshotLatestId "$@"; } +kopiaSnapshotListFiles() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSnapshotListFiles "$@"; } kopiaSnapshotsJson() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSnapshotsJson "$@"; } +kopiaSystemSnapshotsJson() { source "${install_scripts_dir}backup/engine/kopia_snapshots.sh"; kopiaSystemSnapshotsJson "$@"; } _linkdingManage() { source "${install_containers_dir}linkding/scripts/linkding_auth.sh"; _linkdingManage "$@"; } listDockerComposeFiles() { source "${install_scripts_dir}config/docker/docker_list_compose_files.sh"; listDockerComposeFiles "$@"; } localDnsAppHosts() { source "${install_scripts_dir}network/dns/setup_local_dns.sh"; localDnsAppHosts "$@"; } @@ -2340,6 +2388,10 @@ migrateUrlRewriteEnabled() { source "${install_scripts_dir}migrate/migrate_url_r monitoringAppEnabled() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringAppEnabled "$@"; } monitoringInstalledApps() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringInstalledApps "$@"; } monitoringIsInstalled() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringIsInstalled "$@"; } +monitoringRefreshAll() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringRefreshAll "$@"; } +monitoringRefreshGrafana() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringRefreshGrafana "$@"; } +monitoringRefreshPrometheus() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringRefreshPrometheus "$@"; } +monitoringResolveScrapeTags() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringResolveScrapeTags "$@"; } monitoringToggleAppConfig() { source "${install_scripts_dir}network/monitoring/monitoring.sh"; monitoringToggleAppConfig "$@"; } moveFile() { source "${install_scripts_dir}function/file/move_file.sh"; moveFile "$@"; } _nextcloudOcc() { source "${install_containers_dir}nextcloud/scripts/nextcloud_auth.sh"; _nextcloudOcc "$@"; } @@ -2399,6 +2451,7 @@ readTaskField() { source "${install_scripts_dir}crontab/task/crontab_task_proces reconcileConfigFile() { source "${install_scripts_dir}config/core/variables/config_scan_variables.sh"; reconcileConfigFile "$@"; } reconcileContainersTopOwnership() { source "${install_scripts_dir}function/permission/libreportal_folders.sh"; reconcileContainersTopOwnership "$@"; } reconcileDockerOwnership() { source "${install_scripts_dir}function/permission/libreportal_folders.sh"; reconcileDockerOwnership "$@"; } +_reconcileSplitValueComment() { source "${install_scripts_dir}config/core/variables/config_scan_variables.sh"; _reconcileSplitValueComment "$@"; } reconcileWebuiDirOwnership() { source "${install_scripts_dir}function/permission/libreportal_folders.sh"; reconcileWebuiDirOwnership "$@"; } recoverOrphans() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; recoverOrphans "$@"; } removeEmptyLineAtFileEnd() { source "${install_scripts_dir}function/file/empty_line/remove_line.sh"; removeEmptyLineAtFileEnd "$@"; } @@ -2497,6 +2550,7 @@ setupHeadscaleLocalhost() { source "${install_containers_dir}headscale/scripts/h setupHeadscaleRemote() { source "${install_containers_dir}headscale/scripts/headscale_setup_remote.sh"; setupHeadscaleRemote "$@"; } setupHeadscaleUser() { source "${install_containers_dir}headscale/scripts/headscale_user.sh"; setupHeadscaleUser "$@"; } setupHeadscaleVariables() { source "${install_scripts_dir}network/variables/headscale_variables.sh"; setupHeadscaleVariables "$@"; } +setupLocalDnsRewrites() { source "${install_scripts_dir}network/dns/setup_local_dns.sh"; setupLocalDnsRewrites "$@"; } setupTaskDir() { source "${install_scripts_dir}crontab/task/crontab_task_processor.sh"; setupTaskDir "$@"; } setupWizardMarkComplete() { source "${install_scripts_dir}setup/setup_lock.sh"; setupWizardMarkComplete "$@"; } setupWizardReset() { source "${install_scripts_dir}setup/setup_lock.sh"; setupWizardReset "$@"; } @@ -2601,9 +2655,11 @@ webuiRunUpdate() { source "${install_scripts_dir}update/check_update.sh"; webuiR webuiSetConfigOptions() { source "${install_scripts_dir}webui/data/generators/config/webui_cli_config_set.sh"; webuiSetConfigOptions "$@"; } webuiSyncAppIcon() { source "${install_scripts_dir}webui/data/utils/webui_app_icons.sh"; webuiSyncAppIcon "$@"; } webuiSyncAppIcons() { source "${install_scripts_dir}webui/data/utils/webui_app_icons.sh"; webuiSyncAppIcons "$@"; } +webuiSystemApps() { source "${install_scripts_dir}webui/data/generators/system/webui_system_metrics.sh"; webuiSystemApps "$@"; } webuiSystemDisk() { source "${install_scripts_dir}webui/data/generators/system/webui_system_disk.sh"; webuiSystemDisk "$@"; } webuiSystemInfo() { source "${install_scripts_dir}webui/data/generators/system/webui_system_info.sh"; webuiSystemInfo "$@"; } webuiSystemMemory() { source "${install_scripts_dir}webui/data/generators/system/webui_system_memory.sh"; webuiSystemMemory "$@"; } +webuiSystemMetrics() { source "${install_scripts_dir}webui/data/generators/system/webui_system_metrics.sh"; webuiSystemMetrics "$@"; } webuiSystemUpdate() { source "${install_scripts_dir}webui/data/generators/system/webui_system_update.sh"; webuiSystemUpdate "$@"; } webuiSystemUpdateCheck() { source "${install_scripts_dir}webui/data/generators/system/webui_system_update.sh"; webuiSystemUpdateCheck "$@"; } webuiUpdateAppLog() { source "${install_scripts_dir}webui/data/utils/webui_app_log.sh"; webuiUpdateAppLog "$@"; } diff --git a/scripts/source/files/generate_function_manifest.sh b/scripts/source/files/generate_function_manifest.sh index 0cd61de..d857c0a 100644 --- a/scripts/source/files/generate_function_manifest.sh +++ b/scripts/source/files/generate_function_manifest.sh @@ -133,19 +133,24 @@ analyze_file() { next } - # Closing brace at depth 1 ends a function. - if (depth > 0 && stripped == "}") { depth--; next } - - # Track depth roughly for content inside functions. We only need - # to know if depth == 0 for the eager check; bumping on any `{` - # at end-of-line and decrementing on `}` keeps it close enough. + # Inside a function body: track brace depth so we know when the + # function ends (returns to depth 0). Count open + close braces + # per line symmetrically — embedded awk/sed/perl scripts close + # their inline blocks mid-line (the close brace runs together + # with a single-quote and the input filename, all on one line). + # The previous "decrement only on a bare close brace" rule missed + # those, leaving the depth counter stuck > 0 and silently + # dropping every function defined later in the same file. + # Per-line net delta picks them up. False positives from braces + # inside string literals could under/over-count, but the clamp + # at 0 plus the next legitimate funcname() header re-anchors. if (depth > 0) { - # heredocs, strings — ignore detailed accounting; the only - # thing that matters is staying > 0 until the closing }. - if (stripped ~ /\{[[:space:]]*$/) depth++ - # Multiple `}` on a line: count them. - n_close = gsub(/\}/, "&", stripped) - # don’t double-count the line we ate above + tmp = stripped + n_open = gsub(/\{/, "{", tmp) + tmp = stripped + n_close = gsub(/\}/, "}", tmp) + depth += (n_open - n_close) + if (depth < 0) depth = 0 next }