#! /usr/bin/env bash

# file      : msvc-common/msvc-cl-common
# copyright : Copyright (c) 2014-2019 Code Synthesis Ltd
# license   : MIT; see accompanying LICENSE file

# Note: shouldn't be executed directly, src_dir must be set.

# Common cl.exe driver that expects the VCBIN, INCLUDE, and, if running as a
# linker, SDKBIN, LIB variables to be set for the specific MSVC
# version/configuration.

source "$src_dir/msvc-common/msvc-common"

# File descriptor where the diagnostics will be sent. Unless STDOUT is used
# for something else (e.g., /E, /EP), cl.exe sends the diagnostics there.
# Otherwise it goes to STDERR. Plus /P behaves like /E for some reason.
#
diag=1

# Translate absolute paths from POSIX to Windows. Use bash array to store
# arguments in case they contain spaces.
#
# This needs to be done for both certain option values and arguments.
# Arguments are tricky in that unless we recognize every option, and option
# may look a lot like an absolute POSIX path (e.g., /nologo). The heuristics
# that we are going to use here is that if the argument starts with / and
# contains at least one more /, then we consider it an argument. Otherwise --
# an options. We will also explicitly recognize certain options, like /D,
# which may not fit this scheme well.
#
# Note that the order of the cases is important. Specifically, we want, e.g.,
# /D before /D*.
#
# Note also that cl.exe options are case-sensitive.
#
args=()

# Whether to export IFCPATH. We suppress it if /module:stdIfcDir is specified
# since IFCPATH path (misguidedly) takes precedence.
#
ifc=true

while [ $# -gt 0 ]; do
  case $1 in

    # /I <dir>, /AI <dir>
    # /module:output <file>, /module:reference <file>
    # /module:search <dir>, /module:stdIfcDir <dir>
    #
    [/-]I                | \
    [/-]AI               | \
    [/-]module:output    | \
    [/-]module:reference | \
    [/-]module:search    | \
    [/-]module:stdIfcDir)
      if [ "$1" = "/module:stdIfcDir" ]; then
	ifc=
      fi

      args=("${args[@]}" "$1")
      shift
      args=("${args[@]}" "$(translate $1)")
      shift
      ;;

    # /I<dir>
    #
    [/-]I*)
      args=("${args[@]}" "$(split_translate 2 $1)")
      shift
      ;;

    # /AI<dir>
    #
    [/-]AI*)
      args=("${args[@]}" "$(split_translate 3 $1)")
      shift
      ;;

    # /F*: <file>
    #
    [/-]F[adeimoprR]:)
      args=("${args[@]}" "$1")
      shift
      args=("${args[@]}" "$(translate $1)")
      shift
      ;;

    # /F*<file>, /T{p,c}<file>, /Yu<file>.
    #
    [/-]F[adeimoprRUI]* | \
    [/-]Tp*             | \
    [/-]Tc*             | \
    [/-]Yu*)
      args=("${args[@]}" "$(split_translate 3 $1)")
      shift
      ;;

    # /doc<file>
    #
    [/-]doc*)
      args=("${args[@]}" "$(split_translate 4 $1)")
      shift
      ;;

    # @<file>
    #
    @*)
      args=("${args[@]}" "$(split_translate 1 $1)")
      shift
      ;;

    # Handle other options with separate values. This makes sure we don't try
    # to path-translate them.
    #
    [/-]D | \
    [/-]U | \
    [/-]link)
      args=("${args[@]}" "$1")
      shift
      args=("${args[@]}" "$1")
      shift
      ;;

    # Handle other options with combined values that could possibly be
    # interpreted as paths, for example /DFOO=foo/bar.
    #
    [/-]D* | \
    [/-]V* | \
    [/-]Yl*)
      args=("${args[@]}" "$1")
      shift
      ;;

    # Detect /E, /P, and /EP -- they change where the diagnostics is sent.
    #
    [/-]E | \
    [/-]P | \
    [/-]EP)
      diag=2
      args=("${args[@]}" "$1")
      shift
      ;;

    # Option or argument.
    #
    *)
      # If contains at least two slashes, treat it as a path.
      #
      if [[ "$1" == /*/* ]]; then
        args=("${args[@]}" "$(translate $1)")
      else
        args=("${args[@]}" "$1")
      fi
      shift
      ;;
  esac
done

export INCLUDE
export LIB

if [ "$ifc" = "true" ]; then
  export IFCPATH
fi

# The linker may need to run mt.exe which is in the SDK.
#
export WINEPATH="$VCBIN;$VCDLL;$SDKBIN;$WINEPATH"

msvc_exec $diag "$VCBIN\\cl.exe" "${args[@]}"