# Shared setup for the run_magic* launchers -- sourced, not run directly.
#
# Generated by configure from scripts/magic_run_common.sh.in.  It stages a
# CAD_ROOT directory of *symlinks* into the build (generated) and source trees --
# the same layout `make install` copies, but instantly and always reflecting the
# latest build -- and exports the environment magic needs to start straight from
# the build tree without `make install`.
#
# See magic's runtime file discovery: MAGIC_SYS_PATH = ". $CAD_ROOT/magic/sys
# $CAD_ROOT/magic/sys/current" (utils/paths.h) for tech/glyphs/fonts/styles, the
# system .magicrc at $CAD_ROOT/magic/sys/.magicrc, and (since tcltk/tcldir.h)
# magic.tcl / tclmagic / auto_path at $CAD_ROOT/magic/tcl.
#
# ---------------------------------------------------------------------------
# Environment overrides (every value below can be pre-set in the environment;
# each is initialized with ${VAR:-<default>} so the caller's value wins):
#
#   CAD_ROOT        Root of the staged runtime tree.  Default: the build tree's
#                   own $builddir/CAD_DIR (a directory of symlinks, created on
#                   first run).  Point it elsewhere to reuse a shared/installed
#                   tree instead of staging one.
#   MAGIC_WISH      The "wish" binary magic uses for the Tk console.  Default:
#                   WISH, i.e. the wish detected by configure to match the Tcl/Tk
#                   this build linked against (--with-tk / --with-wish).  A build
#                   against a non-standard Tk therefore uses the correct absolute
#                   wish automatically; override to force a different one.
#   WISH            Same as above; MAGIC_WISH defaults from it.  Baked default is
#                   the configure-detected wish (may be empty on a --disable-tcl
#                   build -- the launchers use the self-contained magicexec and do
#                   not require an external wish).
#   TCLSH           tclsh matching this build's Tcl (--with-tcl).  Provided for
#                   convenience/diagnostics; may be empty if configure found none.
#   MAGIC_BUILDDIR  Absolute build-tree top.  Default: baked @abs_top_builddir@.
#   MAGIC_SRCDIR    Absolute source-tree top.  Default: baked @abs_top_srcdir@.
#
# Any value that is inherited from the environment (or a baked default that no
# longer resolves) is sanity-checked below; problems are reported on stderr as
# non-fatal warnings to aid diagnosis -- see magic_check_env().
# ---------------------------------------------------------------------------

# Record which values the caller supplied (vs. the configure-baked default) so
# diagnostics can name the origin, then fall back to the baked-in defaults.
# ${VAR+x} is "x" only when VAR is already set -- safe under `set -u`.
_origin_MAGIC_BUILDDIR="build default"; [ -n "${MAGIC_BUILDDIR+x}" ] && _origin_MAGIC_BUILDDIR=environment
_origin_MAGIC_SRCDIR="build default";   [ -n "${MAGIC_SRCDIR+x}" ]   && _origin_MAGIC_SRCDIR=environment
_origin_CAD_ROOT="build default";       [ -n "${CAD_ROOT+x}" ]       && _origin_CAD_ROOT=environment
_origin_WISH="build default";           [ -n "${WISH+x}" ]           && _origin_WISH=environment
_origin_MAGIC_WISH="build default";     [ -n "${MAGIC_WISH+x}" ]     && _origin_MAGIC_WISH=environment
_origin_TCLSH="build default";          [ -n "${TCLSH+x}" ]          && _origin_TCLSH=environment

MAGIC_BUILDDIR="${MAGIC_BUILDDIR:-@abs_top_builddir@}"
MAGIC_SRCDIR="${MAGIC_SRCDIR:-@abs_top_srcdir@}"
SHDLIB_EXT="${SHDLIB_EXT:-@SHDLIB_EXT@}"

CAD_ROOT="${CAD_ROOT:-${MAGIC_BUILDDIR}/CAD_DIR}"
export CAD_ROOT
MAGIC_SYS="${CAD_ROOT}/magic/sys"
MAGIC_TCL="${CAD_ROOT}/magic/tcl"

# wish/tclsh that match the Tcl/Tk this tree was configured against.
WISH="${WISH:-@WISH_EXE@}"
TCLSH="${TCLSH:-@TCLSH_EXE@}"
# tkcon.tcl launches the console via ${MAGIC_WISH:=wish}; hand it the matching one.
MAGIC_WISH="${MAGIC_WISH:-$WISH}"
[ -n "$MAGIC_WISH" ] && export MAGIC_WISH

# One warning helper for all launchers.
magic_warn() { printf 'run_magic: warning: %s\n' "$*" >&2; }

# _magic_check NAME KIND ORIGIN VALUE
#   KIND: mustdir  -- must exist and be a directory
#         newdir   -- may be absent (created later); if present must be a directory
#         exec     -- must exist, be a regular file, and be executable
#         optexec  -- empty is fine (feature not configured); else same as exec
_magic_check() {
    _n="$1"; _k="$2"; _o="$3"; _v="$4"
    case "$_k" in
        optexec) [ -n "$_v" ] || return 0; _k=exec ;;
    esac
    case "$_k" in
        mustdir)
            [ -d "$_v" ] || magic_warn "\$$_n ($_o) = '$_v' is not a directory (build tree moved or removed?)" ;;
        newdir)
            { [ ! -e "$_v" ] || [ -d "$_v" ]; } || \
                magic_warn "\$$_n ($_o) = '$_v' exists but is not a directory" ;;
        exec)
            if [ ! -e "$_v" ]; then
                magic_warn "\$$_n ($_o) = '$_v' does not exist"
            elif [ ! -f "$_v" ]; then
                magic_warn "\$$_n ($_o) = '$_v' is not a regular file"
            elif [ ! -x "$_v" ]; then
                magic_warn "\$$_n ($_o) = '$_v' is not executable"
            fi ;;
    esac
}

# Validate the (possibly environment-inherited) configuration and warn -- never
# fail -- on anything that looks wrong, so a bad override is easy to spot.
magic_check_env() {
    _magic_check MAGIC_BUILDDIR mustdir "$_origin_MAGIC_BUILDDIR" "$MAGIC_BUILDDIR"
    _magic_check MAGIC_SRCDIR   mustdir "$_origin_MAGIC_SRCDIR"   "$MAGIC_SRCDIR"
    _magic_check CAD_ROOT       newdir  "$_origin_CAD_ROOT"       "$CAD_ROOT"
    _magic_check WISH           optexec "$_origin_WISH"           "$WISH"
    # MAGIC_WISH defaults from WISH; only check it separately when it diverges
    # (an explicit MAGIC_WISH override) to avoid a duplicate warning.
    [ "$MAGIC_WISH" = "$WISH" ] || \
        _magic_check MAGIC_WISH optexec "$_origin_MAGIC_WISH"     "$MAGIC_WISH"
    _magic_check TCLSH          optexec "$_origin_TCLSH"          "$TCLSH"
}

# (Re)build the symlink layout.  Idempotent; `ln -sf` relinks so a rebuilt target
# is always current.  Missing globs (a partial build) are tolerated.
magic_stage() {
    local b="$MAGIC_BUILDDIR" s="$MAGIC_SRCDIR"
    mkdir -p "$MAGIC_SYS" "$MAGIC_TCL"

    # --- sys/ : generated tech (build) + display files/glyphs/fonts (source) ---
    ln -sf "$b"/scmos/*.tech                              "$MAGIC_SYS"/ 2>/dev/null || :
    ln -sf "$s"/scmos/*.cmap "$s"/scmos/*dstyle           "$MAGIC_SYS"/ 2>/dev/null || :
    ln -sf "$s"/windows/*.glyphs "$s"/windows/vfont.*     "$MAGIC_SYS"/ 2>/dev/null || :
    ln -sf "$s"/graphics/*.glyphs "$s"/graphics/*.pt3     "$MAGIC_SYS"/ 2>/dev/null || :
    ln -sf "$b"/magic/proto.magicrc                       "$MAGIC_SYS"/.magicrc 2>/dev/null || :
    ln -sf "$b"/magic/proto.initrc                        "$MAGIC_SYS"/.initrc 2>/dev/null || :
    if [ -f "$b"/magic/magicps.pro ]; then
        ln -sf "$b"/magic/magicps.pro "$MAGIC_SYS"/ 2>/dev/null || :
    else
        ln -sf "$s"/magic/magicps.pro "$MAGIC_SYS"/ 2>/dev/null || :
    fi

    # --- tcl/ : source scripts + generated magic.tcl + .so + execs + bitmaps ---
    ln -sf "$s"/tcltk/*.tcl                               "$MAGIC_TCL"/ 2>/dev/null || :
    ln -sf "$b"/tcltk/magic.tcl                           "$MAGIC_TCL"/ 2>/dev/null || :
    ln -sf "$b"/magic/tclmagic${SHDLIB_EXT}               "$MAGIC_TCL"/ 2>/dev/null || :
    ln -sf "$b"/tcltk/magicexec "$b"/tcltk/magicdnull     "$MAGIC_TCL"/ 2>/dev/null || :
    # bitmaps is a *directory*: use -n so a re-stage replaces the existing
    # symlink instead of dereferencing it and dropping a self-link *inside* the
    # source tree (magic/bitmaps/bitmaps -> .../magic/bitmaps).
    ln -sfn "$s"/magic/bitmaps                            "$MAGIC_TCL"/bitmaps 2>/dev/null || :
}

# Split a launcher's argv on the first "--":
#     <tool-opts...> -- <magic-args...>
# Everything before "--" is for the wrapper tool (gdb/valgrind); everything after
# is magic's.  With no "--" present, ALL arguments are treated as magic's -- the
# common case where no tool options are needed.  Results are returned in the
# arrays MAGIC_TOOL_OPTS and MAGIC_ARGS.
magic_split_args() {
    MAGIC_TOOL_OPTS=()
    MAGIC_ARGS=()
    local seen=0 a
    for a in "$@"; do
        if [ "$seen" -eq 0 ] && [ "$a" = "--" ]; then seen=1; continue; fi
        if [ "$seen" -eq 1 ]; then MAGIC_ARGS+=("$a"); else MAGIC_TOOL_OPTS+=("$a"); fi
    done
    if [ "$seen" -eq 0 ]; then
        MAGIC_ARGS=(${MAGIC_TOOL_OPTS[@]+"${MAGIC_TOOL_OPTS[@]}"})
        MAGIC_TOOL_OPTS=()
    fi
}

# Fail early with a clear message if the build has not produced the binaries yet.
magic_require_built() {
    if [ ! -x "$MAGIC_BUILDDIR/tcltk/magicexec" ] && \
       [ ! -x "$MAGIC_BUILDDIR/tcltk/magicdnull" ]; then
        echo "error: magic is not built yet -- run 'make' in ${MAGIC_BUILDDIR} first." >&2
        exit 1
    fi
}

# Validate the environment as soon as this file is sourced (warnings only).
magic_check_env
