#!/usr/bin/env bash
set -euo pipefail

root="${TEST_SRCDIR}/${TEST_WORKSPACE}"

declare -A baseline=(
  ["auth/auth_store.c"]=4
  ["deita/d_sqlite.c"]=4
  ["design_system/main.c"]=2
  ["dowa/d_memory.c"]=15
  ["dowa/dowa.h"]=1
  ["dowa/d_string.c"]=3
  ["dowa/stb_ds.h"]=4
  ["markdown_converter/markdown_to_html.c"]=40
  ["mrjunejune/conversation_api.c"]=7
  ["mrjunejune/conversation_store.c"]=4
  ["mrjunejune/inference_bridge.c"]=5
  ["mrjunejune/latex_renderer.c"]=15
  ["mrjunejune/main.c"]=8
  ["mrjunejune/template_renderer.c"]=4
  ["mrjunejune/test/inference_bridge_fake_sidecar.c"]=1
  ["mrjunejune/test/integration_test.c"]=9
  ["mrjunejune/test/template_renderer_test.c"]=6
  ["postdog/main.c"]=14
  ["s3/s3_uploader.c"]=2
  ["s3/tests/s3_uploader_test.c"]=5
  ["seobeo/os/s_linux_edge.c"]=1
  ["seobeo/os/s_macos_edge.c"]=1
  ["seobeo/s_http_client.c"]=8
  ["seobeo/snapshot_creator.c"]=1
  ["seobeo/s_network.c"]=11
  ["seobeo/s_sse.c"]=3
  ["seobeo/s_web.c"]=4
  ["seobeo/s_websocket.c"]=24
  ["seobeo/s_websocket_common.c"]=2
  ["seobeo/s_websocket_server.c"]=18
  ["seobeo/s_worker.c"]=22
  ["seobeo/tests/seobeo_request_context_test.c"]=3
  ["seobeo/tests/seobeo_response_test.c"]=4
  ["seobeo/tests/seobeo_sigpipe_test.c"]=2
  ["sori/main.c"]=3
)

failed=0
while IFS= read -r -d '' file; do
  relative="${file#${root}/}"
  if [[ "${relative}" == third_party/* ]]; then
    continue
  fi
  count="$(
    { grep -Eo '\b(malloc|calloc|realloc|free)[[:space:]]*\(' "${file}" || true; } |
      wc -l |
      tr -d ' '
  )"
  allowed="${baseline[${relative}]:-0}"
  if (( count > allowed )); then
    printf '%s: raw allocation count increased from %d to %d\n' \
      "${relative}" "${allowed}" "${count}" >&2
    failed=1
  fi
done < <(
  find -L "${root}" \
    \( -path "${root}/bazel-*" -o -path "${root}/external" -o -path "${root}/third_party" \) \
    -prune -o \
    -type f \( -name '*.c' -o -name '*.h' \) -print0
)

if (( failed )); then
  cat >&2 <<'EOF'
First-party C must use Dowa_Arena for scoped allocation.
Do not add malloc/calloc/realloc/free. Refactor existing ownership or, for a
genuine allocator/runtime boundary, document the exception and deliberately
update the reviewed baseline.
EOF
  exit 1
fi
