#!/bin/sh

#
# sysdep-mod-exec
#
# Execute a module.
#

#
# Support subprograms.
#

#
# Mark module as successful or failed.
#

SDM_module_succeed()
{
  STATUS_FILE="${SYSDEP_STATUS_DIRECTORY}/${SYSDEP_MODULE}"
  ${SYSDEP_UTIL_ECHO} 'succeeded' > "${STATUS_FILE}" ||
    SYSDEP_ERROR "could not write ${STATUS_FILE}"
}

SDM_module_fail()
{
  STATUS_FILE="${SYSDEP_STATUS_DIRECTORY}/${SYSDEP_MODULE}"
  ${SYSDEP_UTIL_ECHO} 'failed' > "${STATUS_FILE}" ||
    SYSDEP_ERROR "could not write ${STATUS_FILE}"
}

SDM_module_fatal()
{
  SDM_module_fail
  SYSDEP_FATAL "$1"
}

SDM_module_exit_success()
{
  SDM_module_succeed || SDM_module_fail || ${SYSDEP_UTIL_EXIT} 1
  ${SYSDEP_UTIL_EXIT} 0
}

#
# Move created files out of working directory into output directory.
#

SDM_files_move()
{
  for file in ${SDM_CREATES}
  do
    if [ "${file}" = "sysdeps.out" ]
    then
      ${SYSDEP_UTIL_CAT} "$file" >> "${SYSDEP_OUTPUT_DIRECTORY}/$file"
      SYSDEP_REMOVE "${file}"
    else
      ${SYSDEP_UTIL_CP} "$file" "${SYSDEP_OUTPUT_DIRECTORY}/$file"
      SYSDEP_REMOVE "${file}"
    fi
  done
}

#
# Convert list of macro names into flattened string with each macro
# name prefixed with '-D'.
#
# XXX: Do all compilers accept -D?
#

SDM_flatten_defines()
{
  d=""
  if [ ! -z "$1" ]
  then
    for tag in $1
    do
      d="-D${tag} ${d}"
    done
    ${SYSDEP_UTIL_ECHO} "$d"
  fi
}

#
# Add given list of directories to standard search paths.
#

SDM_paths_add()
{
  for p in $1; do SYSDEP_STDINC="$p/include $p ${SYSDEP_STDINC}"; done
  for p in $1; do SYSDEP_STDLIB="$p/lib $p ${SYSDEP_STDLIB}"; done
}

#
# Concatentate each element of given list of path components
# to each component of the standard search paths and combine
# the two resulting lists.
#

SDM_paths_extend()
{
  for d in ${SYSDEP_STDINC}
  do
    for e in $1; do SYSDEP_STDINC="$d/$e ${SYSDEP_STDINC}"; done
  done
  for d in ${SYSDEP_STDLIB}
  do
    for e in $1; do SYSDEP_STDLIB="$d/$e ${SYSDEP_STDLIB}"; done
  done
}

#
# Strip leading SYSDEP_OS_ tag from operating system name and
# convert to lowercase.
#

SDM_os_tolower()
{
  ${SYSDEP_UTIL_ECHO} ${SYSDEP_OS} | ${SYSDEP_UTIL_SED} -e 's/SYSDEP_OS_//g' | tr [A-Z] [a-z]
}

#
# Obtain list of files that the current module creates.
#

SDM_CREATES=`${SYSDEP_UTIL_CAT} creates` || SDM_module_fatal "could not read 'creates' file"
SDM_CREATES="${SDM_CREATES} sysdeps.out"

#
# Execute module.
#

#
# Ensure a clean environment.
#

SYSDEP_REMOVE ${SDM_CREATES}        || SDM_module_fatal "could not clean up created files"
${SYSDEP_UTIL_TOUCH} ${SDM_CREATES} || SDM_module_fatal "could not create empty files"

#
# Execute custom script if present.
#

if [ -x "custom" ]
then
  ./custom ${SDM_CREATES}
  RETURN_CODE=$?

  SDM_files_move

  if [ ${RETURN_CODE} -eq 0 ]
  then
    SDM_module_exit_success
  else
    SYSDEP_ERROR "custom program reported failure"
    SDM_module_fail
    ${SYSDEP_UTIL_EXIT} 0
  fi
else
  if [ -f "custom" ]
  then
    SDM_module_fatal "'custom' exists but is not executable"
  fi
fi

#
# Create output file.
#

OUTPUT_FILE="`${SYSDEP_LINE} 1 < creates`" ||
  SDM_module_fatal "could not determine output file"
${SYSDEP_UTIL_TOUCH} ${OUTPUT_FILE} ||
  SDM_module_fatal "could not create '${OUTPUT_FILE}'"

if [ -f "defines" ]
then
  DEFINES="`${SYSDEP_UTIL_CAT} defines |
    ${SYSDEP_UTIL_AWK} -F: '{print $1}' |
    ${SYSDEP_UTIL_TR} -d ' '`" ||
    SDM_module_fatal "could not read 'defines'"
fi

#
# Read OS specific definitions.
#

OS_LOWER=`SDM_os_tolower` ||
  SDM_module_fatal "could not convert OS string to lowercase"

if [ -f "os_ext/${OS_LOWER}/defines" ]
then
  DEFINES="`${SYSDEP_UTIL_CAT} os_ext/${OS_LOWER}/defines |
    ${SYSDEP_UTIL_AWK} -F: '{print $1}' |
    ${SYSDEP_UTIL_TR} -d ' '`" ||
    SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/defines'"
fi
if [ -f flags ]
then
  EXTRA_FLAGS="`${SYSDEP_LINE} 1 < flags`" ||
    SDM_module_fatal "could not read 'flags'"
fi
if [ -f "os_ext/${OS_LOWER}/flags" ]
then
  EXTRA_FLAGS="${EXTRA_FLAGS} `${SYSDEP_LINE} 1 < os_ext/${OS_LOWER}/flags`" ||
    SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/flags'"
fi

#
# Try config binary if requested
#

if [ -f "config_bin" ]
then
  CONFIG_BINARY="`${SYSDEP_LINE} 1 < config_bin`" ||
    SDM_module_fatal "could not read 'config_bin'"
  CONFIG_BINARY_ARGS="`${SYSDEP_LINE} 1 < config_bin_args`" ||
    SDM_module_fatal "could not read 'config_bin_args'"

  FLAGS=`${SYSDEP_TRY_CONFIG_BIN} "${CONFIG_BINARY}" "${CONFIG_BINARY_ARGS}"` ||
    SYSDEP_ERROR "config binary '${CONFIG_BINARY}' failed"

  if [ ! -z "${FLAGS}" ]
  then
    FINAL_DEFINES=`SDM_flatten_defines "${DEFINES}"` ||
      SDM_module_fatal "error flattening preprocessor defines"
    FINAL_OUTPUT="${FLAGS} ${FINAL_DEFINES} ${EXTRA_FLAGS}"

    ${SYSDEP_UTIL_ECHO} "${FINAL_OUTPUT}" >> "${OUTPUT_FILE}" ||
      SDM_module_fatal "could not write ${OUTPUT_FILE}"
    ${SYSDEP_UTIL_ECHO} "${SYSDEP_MODULE}: ${FINAL_OUTPUT}" >> "sysdeps.out" ||
      SDM_module_fatal "could not write sysdeps.out"

    SDM_files_move || SDM_module_fatal "error moving files"
    SDM_module_exit_success
  fi
fi

#
# Try pkg-config if requested
#

if [ -f "pkg" ]
then
  PKG_CONFIG_ARGS="`${SYSDEP_LINE} 1 < pkg_config_args`" ||
    SDM_module_fatal "could not read 'pkg_config_args'"
  PACKAGE="`${SYSDEP_LINE} 1 < pkg`" ||
    SDM_module_fatal "could not read 'pkg'"

  FLAGS=`${SYSDEP_TRY_PKG_CONFIG} "${PACKAGE}" "${PKG_CONFIG_ARGS}"` ||
    SYSDEP_ERROR "pkg-config failed for '${PACKAGE}'"

  if [ ! -z "${FLAGS}" ]
  then
    FINAL_DEFINES=`SDM_flatten_defines "${DEFINES}"` ||
      SDM_module_fatal "error flattening preprocessor defines"
    FINAL_OUTPUT="${FLAGS} ${FINAL_DEFINES} ${EXTRA_FLAGS}"

    ${SYSDEP_UTIL_ECHO} "${FINAL_OUTPUT}" >> "${OUTPUT_FILE}" ||
      SDM_module_fatal "could not write ${OUTPUT_FILE}"
    ${SYSDEP_UTIL_ECHO} "${SYSDEP_MODULE}: ${FINAL_OUTPUT}" >> "sysdeps.out" ||
      SDM_module_fatal "could not write sysdeps.out"

    SDM_files_move || SDM_module_fatal "error moving files"
    SDM_module_exit_success
  fi
fi

#
# Fall back to manual search.
#

if [ -f "path_add" ]
then
  SDM_paths_add "`${SYSDEP_UTIL_CAT} path_add`" ||
    SDM_module_fatal "could not read 'path_add'"
fi
if [ -f "os_ext/${OS_LOWER}/path_add" ]
then
  SDM_paths_add "`${SYSDEP_UTIL_CAT} os_ext/${OS_LOWER}/path_add`" ||
    SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/path_add'"
fi
if [ -f "path_ext" ]
then
  SDM_paths_extend "`${SYSDEP_UTIL_CAT} path_ext`" ||
    SDM_module_fatal "could not read 'path_ext'"
fi
if [ -f "os_ext/${OS_LOWER}/path_ext" ]
then
  SDM_paths_extend "`${SYSDEP_UTIL_CAT} os_ext/${OS_LOWER}/path_ext`" ||
    SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/path_ext'"
fi

#
# Header file search.
#

if [ -f "header" ]
then
  HEADER_FILE="`${SYSDEP_LINE} 1 < header`" ||
    SDM_module_fatal "could not read 'header'"

  if [ -f "os_ext/${OS_LOWER}/header" ]
  then
    HEADER_FILE="`${SYSDEP_LINE} 1 < os_ext/${OS_LOWER}/header`" ||
      SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/header'"
  fi

  FLAGS=`${SYSDEP_TRY_MANUAL} "${HEADER_FILE}" "${SYSDEP_STDINC}" "-I"` ||
    SYSDEP_ERROR "manual search for ${HEADER_FILE} failed"

  if [ ! -z "${FLAGS}" ]
  then
    FINAL_DEFINES=`SDM_flatten_defines "${DEFINES}"` ||
      SDM_module_fatal "error flattening preprocessor defines"
    FINAL_OUTPUT="${FLAGS} ${FINAL_DEFINES} ${EXTRA_FLAGS}"

    ${SYSDEP_UTIL_ECHO} "${FINAL_OUTPUT}" >> "${OUTPUT_FILE}" ||
      SDM_module_fatal "could not write ${OUTPUT_FILE}"
    ${SYSDEP_UTIL_ECHO} "${SYSDEP_MODULE}: ${FINAL_OUTPUT}" >> "sysdeps.out" ||
      SDM_module_fatal "could not write sysdeps.out"

    SDM_files_move || SDM_module_fatal "error moving files"
    SDM_module_exit_success
  fi
fi

#
# Dynamic library search.
#

if [ -f "dynamic_lib" ]
then
  DYNAMIC_LIB="`${SYSDEP_LINE} 1 < dynamic_lib`" ||
    SDM_module_fatal "could not read 'dynamic_lib'"

  if [ -f "os_ext/${OS_LOWER}/dynamic_lib" ]
  then
    DYNAMIC_LIB="`${SYSDEP_LINE} 1 < os_ext/${OS_LOWER}/dynamic_lib`" ||
      SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/dynamic_lib'"
  fi

  LIBRARY_FILE="lib${DYNAMIC_LIB}.${SYSDEP_LIBSUFFIX}"

  FLAGS=`${SYSDEP_TRY_MANUAL} "${LIBRARY_FILE}" "${SYSDEP_STDLIB}" "-L"` ||
    SYSDEP_ERROR "manual search for '${LIBRARY_FILE}' failed"

  if [ ! -z "${FLAGS}" ]
  then
    FINAL_OUTPUT="${FLAGS} -l${DYNAMIC_LIB} ${EXTRA_FLAGS}"
    ${SYSDEP_UTIL_ECHO} "${FINAL_OUTPUT}" >> "${OUTPUT_FILE}" ||
      SDM_module_fatal "could not write '${OUTPUT_FILE}'"
    ${SYSDEP_UTIL_ECHO} "${SYSDEP_MODULE}: ${FINAL_OUTPUT}" >> "sysdeps.out" ||
      SDM_module_fatal "could not write 'sysdeps.out'"

    SDM_files_move || SDM_module_fatal "error moving files"
    SDM_module_exit_success
  fi
fi

#
# Static library search.
#

if [ -f "static_lib" ]
then
  STATIC_LIBRARY="`${SYSDEP_LINE} 1 < static_lib`" ||
    SDM_module_fatal "could not read 'static_lib'"

  if [ -f "os_ext/${OS_LOWER}/static_lib" ]
  then
    STATIC_LIBRARY="`${SYSDEP_LINE} 1 < os_ext/${OS_LOWER}/static_lib`" ||
      SDM_module_fatal "could not read 'os_ext/${OS_LOWER}/static_lib'"
  fi

  STATIC_LIBRARY_FILE="lib${STATIC_LIBRARY}.a"

  FLAGS=`${SYSDEP_TRY_MANUAL} "${STATIC_LIBRARY_FILE}" "${SYSDEP_STDLIB}" ""` ||
    SYSDEP_ERROR "manual search for '${STATIC_LIBRARY_FILE}' failed"

  if [ ! -z "${FLAGS}" ]
  then
    FINAL_OUTPUT=`printf "%s/%s %s" ${FLAGS} "${STATIC_LIBRARY_FILE}" "${EXTRA_FLAGS}"` ||
      SDM_module_fatal "could not assemble output"

    ${SYSDEP_UTIL_ECHO} "${FINAL_OUTPUT}" >> "${OUTPUT_FILE}" ||
      SDM_module_fatal "could not write to '${OUTPUT_FILE}'"
    ${SYSDEP_UTIL_ECHO} "${SYSDEP_MODULE}: ${FINAL_OUTPUT}" >> "sysdeps.out" ||
      SDM_module_fatal "could not write to 'sysdeps.out'"

    SDM_files_move || SDM_module_fatal "error moving files"
    SDM_module_exit_success
  fi
fi

SYSDEP_INFO "all search types failed"
SDM_module_fail
SDM_files_move || SDM_module_fatal "error moving files"
