#!/usr/bin/env bash
function cli_show_extensions_pre_run() {
declare -g USE_TMPFS="${USE_TMPFS:-no}"
return 0
}
function cli_show_extensions_run() {
declare format="${SHOW_EXTENSIONS:-list}"
display_alert "Scanning sources for extension hook points" "lib, extensions, config" "info"
declare -a hook_files=()
mapfile -t -d '' hook_files < <(grep -r -I -l --null "call_extension_method" "${SRC}/lib" "${SRC}/extensions" "${SRC}/config" 2> /dev/null)
if [[ ${#hook_files[@]} -eq 0 ]]; then
display_alert "No hook call sites found" "nothing to list" "warn"
return 0
fi
printf '%s\0' "${hook_files[@]}" |
xargs -0 awk '
BEGIN { dq = "\042"; FSEP = "\002"; NLEN = "\001" } # double-quote, field-sep and newline-placeholder bytes
# Collect every double-quoted token from a string into arr[1..n]; returns n.
function extract_quotes(s, arr, i, c, inq, cur, n) {
n = 0; inq = 0; cur = ""
for (i = 1; i <= length(s); i++) {
c = substr(s, i, 1)
if (c == dq) {
if (inq) { arr[++n] = cur; cur = ""; inq = 0 } else { inq = 1 }
} else if (inq) { cur = cur c }
}
return n
}
FNR == 1 { in_heredoc = 0 } # a never-closed heredoc must not bleed across files
{
if (!in_heredoc) {
# A real hook call starts the line (modulo indent): <tab>call_extension_method "name" [compat...] <<- DELIM
# Anchoring on line start skips comments and code that merely mention the function name.
if ($0 ~ /^[ \t]*call_extension_method[ \t]+\042/ && index($0, "<<") > 0) {
call_part = substr($0, 1, index($0, "<<") - 1)
n = extract_quotes(call_part, toks)
if (n >= 1) {
cur_hook = toks[1]
gsub(/\$\{[^}]*\}/, "<branch>", cur_hook) # templated names like ${BRANCH,,} are not literal hooks
compat = ""
for (i = 2; i <= n; i++) compat = compat (compat == "" ? "" : " ") toks[i]
# The heredoc delimiter is the first bare word after "<<", minus "-" and quotes.
rest = substr($0, index($0, "<<") + 2)
sub(/^-/, "", rest); sub(/^[ \t]+/, "", rest)
gsub(/\042/, "", rest); gsub(/\047/, "", rest)
split(rest, da, /[ \t]+/); delim = da[1]
in_heredoc = 1; body = ""
}
}
next
}
# Inside the heredoc body; a line equal to the delimiter (ignoring indent) closes it.
line = $0; trimmed = line; sub(/^[ \t]+/, "", trimmed)
if (trimmed == delim) {
in_heredoc = 0
print cur_hook FSEP compat FSEP body # one record per hook; sorted/formatted downstream
next
}
sub(/^\t+/, "", line) # mimic "<<-" tab stripping
body = (body == "" ? line : body NLEN line)
}
' | LC_ALL=C sort -u | format="${format}" awk -F "\002" '
BEGIN {
if (ENVIRON["format"] == "docs") {
print "# Armbian build system extension hook points"
print "- Generated by '\''./compile.sh show-extensions SHOW_EXTENSIONS=docs'\'' from the build sources."
print "- Hooks are listed alphabetically; the build invokes them in code order, not this order."
print ""
}
}
!seen[$1]++ { # dedup hook points called from more than one site
if (ENVIRON["format"] != "docs") { print $1; next }
nlines = split($3, bl, "\001")
summary = bl[1]
sub(/^[ \t]*#+[ \t]*/, "", summary) # strip leading "#" so the summary cannot become a heading inside the blockquote
print "### `" $1 "`"
print "> " summary
if (nlines >= 2) {
print ""
for (j = 2; j <= nlines; j++) print bl[j]
}
if ($2 != "") {
print ""
print "Also known as (for backwards compatibility only):"
nc = split($2, ca, " ")
for (j = 1; j <= nc; j++) print "- `" ca[j] "`"
}
print ""
}
'
}