#!/bin/sh
#
# Script to configure "staticability" of plugins
# author: pancake // nopcode
# update: 2026-01-15
#

LANG=C
LC_ALL=C
LOADLIBS=1
TARGET_OSTYPE="${USEROSTYPE}"

ostype_ext() {
	case "$1" in
	windows|mingw32)
		echo dll
		;;
	darwin)
		echo dylib
		;;
	*)
		echo so
		;;
	esac
}

update_ext() {
	if [ -n "$EXT_SO" ]; then
		EXT="${EXT_SO}"
		return
	fi
	if [ -n "$TARGET_OSTYPE" ]; then
		EXT=$(ostype_ext "$TARGET_OSTYPE")
		return
	fi
	EXT=so
	[ "`uname`" = Darwin ] && EXT=dylib
}

update_ext

export LANG
export LC_ALL

list () {
  for a in $STATIC ; do echo "static  $a" ; done
  for a in $SHARED ; do echo "shared  $a" ; done
  exit 0
}

help () {
  echo "Usage: ./configure-plugins [options]"
  echo "  -n                   do nothing.. do not generate any file"
  echo "  --list               list all static and shared plugins"
  echo "  --rm-static [dir]    remove plugins that are already in core from dir"
  echo "  --static [name ..]   define named plugin as static"
  echo "  --shared [name ..]   define named plugin as shared"
  echo "  --help, -h           display this helpful message"
  echo "NOTE: static plugins are compiled inside the owner library"
  exit 0
}

cfg=./plugins.cfg

if [ ! -f "$cfg" ]; then
  echo "configure-plugins: Copying dist/plugins-cfg/plugins.def.cfg"
  cp -f dist/plugins-cfg/plugins.def.cfg plugins.cfg
fi

load () {
  if [ -e $cfg ]; then
    echo "configure-plugins: Loading $cfg .."
    . $cfg
  else
    echo "configure-plugins: Loading $1 .."
    . "$1"
  fi
}


if [ -f libr/xps/static.cfg ]; then
  EXTERNAL_STATIC=$(cat libr/xps/static.cfg)
  echo "[INFO] Statically linking third-party plugins: `echo ${EXTERNAL_STATIC}`"
else
  EXTERNAL_STATIC=""
  echo "[INFO] No third-party static plugins"
fi

generate_configh () {
  plugins=""
  oldlib=""
  for a in ${STATIC} ; do
    lib=$(echo $a | cut -d . -f 1) # library
    plg=$(echo $a | cut -d . -f 2) # plugin name
    if [ ! "$oldlib" = "$lib" ]; then
      [ -n "$oldlib" ] && echo "     0"
      oldlib=$lib
      uclib=$(echo $lib | tr '[a-z]' '[A-Z]')
      echo
      echo "#define R_${uclib}_STATIC_PLUGINS \\"
      plugins="${plugins} __${uclib}"
      # the third party static plugins goes here
      for b in ${EXTERNAL_STATIC} ; do
        extlib=$(echo $b | cut -d . -f 1) # library
        if [ "$lib" = "$extlib" ]; then
          extplg=$(echo $b | cut -d . -f 2) # plugin name
          echo "     &r_${extlib}_plugin_${extplg}, \\"
        fi
      done
    fi
    echo "     &r_${lib}_plugin_${plg}, \\"
  done
  [ -n "$oldlib" ] && echo "     0"

  # CAREFULLY FILL EMPTY PLUGIN ARRAYS
  for a in ${SHARED} ; do
    lib=$(echo $a | cut -d . -f 1) # library
    plg=$(echo $a | cut -d . -f 2) # plugin name
    if [ ! "$oldlib" = "$lib" ]; then
      oldlib=$lib
      uclib=$(echo $lib | tr '[a-z]' '[A-Z]')
      if [ -z "`echo ${plugins} | grep __${uclib}`" ]; then
        plugins="${plugins} __${uclib}"
        echo
        echo "#define R_${uclib}_STATIC_PLUGINS 0"
      fi
    fi
  done
}

generate_asmdinc() {
  plugins=""
  oldlib=""
  for a in ${STATIC} ; do
    lib=$(echo $a | cut -d . -f 1) # library
    plg=$(echo $a | cut -d . -f 2) # plugin name
    echo "(SdbGperf*)&gperf_${plg},"
  done
}

generate_configmk () {
  splugins=""
  plugins=""
  oldlib=""
  for a in `echo "${STATIC} ${SHARED}" | tr " " "\n" | sort` ; do
    lib=$(echo $a | cut -d . -f 1) # library
    plg=$(echo $a | cut -d . -f 2) # plugin name
    if [ ! "$oldlib" = "$lib" ]; then
      [ -n "$oldlib" ] && printf "\n"
      oldlib=$lib
      uclib=$(echo $lib | tr '[a-z]' '[A-Z]')
      printf "STATIC_${uclib}_PLUGINS="
      plugins="${plugins} __${uclib}"
      for b in ${EXTERNAL_STATIC} ; do
        extlib=$(echo $b | cut -d . -f 1)
        if [ "$lib" = "$extlib" ]; then
          extplg=$(echo $b | cut -d . -f 2) # plugin name
          printf " ../xps/p/${extplg}/r2plugin/${lib}/deps.mk"
        fi
      done
    fi
    printf " p/${plg}.mk"
  done

  echo

  for a in ${SHARED} ; do
    lib=$(echo $a | cut -d . -f 1) # library
    plg=$(echo $a | cut -d . -f 2) # plugin name
    uclib=$(echo $lib | tr '[a-z]' '[A-Z]')
    if [ -z "`echo ${splugins} | grep __${uclib}`" ]; then
      splugins="${splugins} __${uclib}"
      printf "SHARED_${uclib}_TARGETS="
    fi
    printf " p/io_${plg}.${EXT}"
  done
  echo
}

generate () {
  echo "configure-plugins: Generating libr/config.h"
  cat libr/config.h.head > libr/config.h

  echo "#define R2_LOADLIBS ${LOADLIBS}" >> libr/config.h
  generate_configh >> libr/config.h
  cat libr/config.h.tail >> libr/config.h

  echo "configure-plugins: Generating libr/asm/d/config.inc"
  generate_asmdinc >> libr/asm/d/config.inc

  echo "configure-plugins: Generating libr/config.mk"
  echo "# This file has been automatically generated by ./configure-plugins" > libr/config.mk
  echo "# The script ./configure-plugins takes the plugins.cfg configuration" >> libr/config.mk
  echo "# When plugins.cfg does not exist it will pick dist/plugins-cfg/plugins.def.cfg" >> libr/config.mk
  cat libr/config.mk.head >> libr/config.mk
  generate_configmk >> libr/config.mk
  cat libr/config.mk.tail >> libr/config.mk
  return
}

add () {
  for a in $1 ; do [ $a = $2 ] && return ; done ; echo $1 $2
}

sub () {
  n="" ; for a in $1 ; do [ $a = $2 ] && continue ; n="$n $a" ; done ; echo $n
}

echo | sort -t. > /dev/null 2>&1
if [ $? = 0 ]; then
  SORT="sort -t."
else
  SORT="sort"
fi

dosort () {
  ( for a in $1 ; do echo $a ; done ) | tr _ Z | ${SORT} | tr Z _
  #( for a in $1 ; do echo $a ; done ) | sort -t. --key=1,1d
}

sort_vars () {
  STATIC=$(dosort "$STATIC")
  SHARED=$(dosort "$SHARED")
}

make_static () {
  STATIC=$(add "$STATIC" $1)
  SHARED=$(sub "$SHARED" $1)
}

make_shared () {
  SHARED=$(add "$SHARED" $1)
  STATIC=$(sub "$STATIC" $1)
}

make_ () { : ; }

MODE=""
DONOTHING=0
DEFCFG=dist/plugins-cfg/plugins.def.cfg

check_conflicts () {
  CONFLICT=0
  for a in $STATIC ; do
    for b in $SHARED ; do
      if [ "$a" = "$b" ]; then
        echo "\x1b[1mError\x1b[0m: Conflict \x1b[44m$a\x1b[0m is defined as STATIC and SHARED"
        CONFLICT=1
      fi
    done
  done
  return $CONFLICT
}

rmstatic() {
  C=0
  if [ -z "$1" ]; then
    echo "Missing argument"
    exit 1
  fi
  for a in ${STATIC} ; do
    b="`echo $a | tr . _`"
    for ext in dll dylib so ; do
      f="$b.$ext"
      if [ -f "$f" ]; then
        C=$(($C+1))
        printf "  $C found\r"
        #echo "rm -f $f"
        rm -f "$f"
      fi
    done
  done
  echo "Removed $C shared plugins that are already static"
}

RMSTATIC=-

while : ; do
  [ -z "$1" ] && break
	case "$1" in
	"--static") MODE=static ; ;;
	"--shared") MODE=shared ; ;;
	"--with-ostype")
		shift
		TARGET_OSTYPE="$1"
		update_ext
		;;
	"--with-ostype="*)
		TARGET_OSTYPE="${1#*=}"
		update_ext
		;;
	"--without-gpl") DEFCFG=./plugins.nogpl.cfg ;;
	"--disable-loadlibs") LOADLIBS=0 ;;
	"--rm-static") RMSTATIC="$2" ; ;;
  "--list") sort_vars ; list ; ;;
  "-n") DONOTHING=1 ; ;;
  "-h"|"--help") help ; ;;
  *) eval make_$MODE $1 ; ;;
  esac
  shift
done

load ${DEFCFG}
sort_vars

if [ - != "${RMSTATIC}" ]; then
  if [ -z "${RMSTATIC}" ]; then
    echo "Missing argument" >&2
    exit
  fi
  if [ -d "${RMSTATIC}" ]; then
    cd "${RMSTATIC}" && rmstatic "${RMSTATIC}"
  fi
  exit 0
fi

check_conflicts || exit 1

[ ${DONOTHING} = 0 ] && generate

echo SHARED: ${SHARED}
echo STATIC: ${STATIC}

exit 0
