#! /usr/bin/bash

#
# The master linker wrapper that makes Microsoft LINK
# look like a Unix-y ld to the configure script and the Makefile.
# Give this file as your linker (LD=wrild) to configure, and all
# will be well.  This is also the script used by wricc, the master
# compiler wrapper, to handle linking.
#
# The options are the same as that used for pcc by David Korn,
# distributed with UWIN.

# TODO:
# Find CL and LINK.  For now, it's OK to use hardcoded paths, or
#   even to assume that they're already on the PATH.  (i.e. this
#   script only works if you installed MSVC with the "Build from
#   command line" option.)
#
# pcc distinguishes between 'ld' and 'ar', which latter seems to be
#   LINK with different arguments.
#
# Append .exe to -o name unless it's already there
#
# DLLs only partially supported yet.  Figure out how to do this right!
# 
# If a /DEF file is passed in -Yl or -YL, don't supply one.  Similarly
# for an /OUT file, etc.  Be smarter about this stuff passed directly
# to the LINKer.
#
# The -l option doesn't do anything yet, because lib_files[] is ignored.
# These files should be augmented with lib*.a or *.lib, and those names
# searched for.
#
# Only .obj/.o files should be passed to dlltool.  This means that
# only they should go into o_files[].  .DEF, .EXP, and .RES files
# should go elsewhere.  (Can library files be passed to dlltool?)


# Names of tools we are using.
# Use the Linker that goes with the compiler (CL).  There's also a
# Cygwin command "link" which we don't want.
LD=$(dirname "$(which cl)")/LINK.EXE

# Declare some arrays and integers
declare -i lib_file_count
declare -i o_file_count

declare -a lib_files
declare -a o_files

# Initialize variables used for storing and counting filename arguments
let lib_file_count=0
let o_file_count=0

# Set defaults
op_static=1   # -Bstatic, build a static library, not a DLL
outfile=	# The -o option: "output file" (use dependent on other flags)
op_debug=0	# -g option - produce an unoptimized version w/ debug C RTL
op_verbose=0	# -V option - show trace information as we go
op_symtable=0	# -Z option - add symbol table to executable
op_subsystem="CONSOLE"   # -T option - subsystem "console" or "windows"
op_dll=0	# -G option - generate a DLL by adding the /dll flag
op_export_all=0	# -Gexport_all_symbols option - when generating a DLL, force
		# all global symbols (functions, variables) to be exported.
		# Note that you must also use the -G option to actually get
		# a DLL.  (Or use /Yl,/dll)
op_create_def=0 # Create a .def file along with the DLL
op_def_name=    # Name of the .DEF file to create (--output-def)
op_add_symtable=0 # -Z option: add a symbol table.

sed_munge_outfile=	# The -s option.  A sed script that modifies "outfile"
			# in case it's automatically generated by libtool
			# (incorrectly).

op_debugging_print=0	# have this script print debugging info

warnlevel=	# -W option, warning level for linker (0-3).

# The command line that follows LINK.
#linkline="-nologo -incremental:no -machine:i386 "
linkline="-nologo -incremental:no "

# The command line that appears at the end of LINK
linkend="KERNEL32.LIB "

# The LIB environment variable used while Linking.
libdirs=""

# Some subfunctions.

# Append argument $1 to linkline, the flags to be passed to LINK.
function Append_To_Linkline
{
	linkline="$linkline$1 "
}

# Append $1 to linkend, the *last* arguments on the LINK command line.
# LINK requires some arguments to come after the object file names.
function Append_To_LinkEnd
{
	linkend="$linkend$1 "
}

# Append argument $1 to libdirs, the directories to be searched for
# additional .LIB files.  This is the same as the LIB environment variable.
function Append_To_Libdirs
{
	libdirs="$libdirs$1;"
}

# get_optarg is used to find the arguments to options.
# $optset is the remainder of the options in this command-line argument
# (e.g. a command-line argument might be -W2; in this case the
#  remainder after W is "2").
# $nextarg is the next command-line argument (e.g. for -o foo.o, the
#  next argument is foo.o.
# returns argument in optarg.  returns optshift=0 if argument immediately
# followed option (-W2), optshift=1 if there was an extra command-line
# argument (-o foo.o).
function get_optarg
{
	# If text immediately follows the option, then that's
	# the argument
	if [ -n "$optset" ]; then
		optarg="$optset"
		let optshift=0
		optset=
	# If no following text, then next command-line arg is the argument
	elif [ -n "$nextarg" ]; then
		optarg="$nextarg"
		let optshift=1
	# It's a fatal error if option is at the end of the line
	else
		echo "Missing required argument for option -$opt" >&2
		Fail_Usage
	fi
}

# Print the usage message and terminate.
function Fail_Usage
{
	local usage
	local ublanks

	usage="Usage: `basename $scriptname`"
	ublanks="${usage//?/ }"  # blanks the same length as usage
	echo   "$usage [-ghqVZ] [-e entry] [-l library]" >&2
	echo "$ublanks [-o outfile] [-s sedcommand] [-u name]" >&2
	echo "$ublanks [-B binding] [-G] [-Gexport-all-symbols]" >&2
	echo "$ublanks [-I dir] [-L dir] [-M runtime]" >&2
	echo "$ublanks [-T subsystem] [-W level]" >&2
	echo "$ublanks [-Y [pass,]argument] [--export-all-symbols]" >&2
	echo "$ublanks [--output-def deffile] [--help]  [file ...]" >&2
	echo >&2
	echo "Enter \"`basename $scriptname` -h\" for help." >&2
	exit 1;
}

# Print a long help message and quit.  This is triggered by the -h option.
function Print_Help_And_Exit
{
echo -n "`basename $0` "
cat <<EOF
is a wrapper for the Microsoft LINK linker that
makes it act more like a Unix-style linker.  It is intended
for use in building Autoconf-based packages, and thus includes
several options for influencing the link process to work around
limitations in libtool.  It runs under Cygwin, and requires either
that the Visual C tools be installed with environment variables
set up to allow them to run from the command line, or that
VCVARS32.BAT be run beforehand.  This script handles only linking
and is usually invoked by wricc.

EOF
echo "Usage: `basename $0` [ options ] [file ...]"
cat <<EOF
OPTIONS
  -e entry        Set the entry point for the program or dynamically
                  linked library.
  -g              Produce a debug build.  A debugging symbol table
                  is created in a .PDB file located in the same
                  directory as the output file.
  -h              Prints this help message.
  -l library      Passed to the linker to link with object library
                  "library".  [Currently not working.]
  -o outfile      Use the pathname outfile for the output file
                  instead of the default filename.exe.
  -q              Turn on Microsoft-compatible extensions.  This
                  activates functionality in the compiler and linker
                  that reduces generality.  Enables the following:
                      [No functions yet.]
  -s sedcommand   Modify the executable or DLL output file name by
                  sed-editing it with "sedcommand" before invoking
                  LINK.  This can be useful when an automatic build
                  system like libtool is creating a DLL with an
                  unwanted name (since you cannot rename a DLL once
                  it's created).
  -u name         Make symbol "name" an unsatisfied external symbol
                  so it will be searched for in a library.
  -B binding      binding can be one of the following, optionally
                  preceded by no[-] to indicate the inverse:
                      dynamic - Build a dynamic-link library.
                      static  - Build a static library.
                   [This flag doesn't work.  I carried it over from
                    pcc but I don't understand what it does there.]
  -G              Create a dynamically-linked library.
  -Gexport-all-symbols
                  Indicates that all symbols in a dynamically-linked
                  library should be exported (not just those marked
                  __declspec(dllexport)).  Does nothing if not building
                  a DLL.  This creates a .DEF file listing all the
                  global symbols, and so it is incompatible with an
                  explicit .DEF file.
  -L dir          Add "dir" to the list of directories containing
                  object-library files.
  -M runtime      Link with one of these C "runtime" libraries:
                      L  -  LIBC: Single-thread application only.
                      T  -  LIBCMT: Multithread application.
                      D  -  MSVCRT runtime DLL (multithread safe).
                  If -g flag is present, the debug versions of these
                  runtimes (LIBCd, LIBCMTd, MSVCRTd).  Default is T.
                  Not necessary if the same option was used in wricc.
  -T subsystem    Set the subsystem type for the executable.
                     console  -  a console-mode program
                     windows  -  a standard Windows program
                  The default is -Tconsole.
  -V              Verbose mode.  Show the command lines given to the
                  underlying tools.
  -W level        Set the warning level to "level".  -W0 is lowest,
                  -W3 is highest.
  -Y pass,argument
                  Pass the given argument to the underlying tool.
                  pass is one of:
                     l  -  pass argument to LINK
                     L  -  pass argument to LINK at the end of the line
                  Note that if "argument" contains spaces, it is
                  necessary to quote it twice: once for the invocation
                  of this script, and again (\\") for the invocation of
                  LINK.
  -Z              Add a symbol table to the generated executable.
                   [This flag doesn't work.  I carried it over from
                    pcc but I don't understand what it does there.]
  --export-all-symbols    Same as -Gexport-all-symbols
  --help          Prints this help message.
  --output-def deffile
                  When constructing a DLL, produce a .DEF file with the
                  name "deffile"

FILES
  *.obj, *.o     Object files to be linked.
  *.lib          Library files  [not well supported]
  *.exp          Exports files  [not well supported]
  *.res          Resource files [not well supported]
  *.def          Module definition files.  Can be used to specify
                  DLL symbols for export.

  All source files are passed to LINK in the order given on the
  command line.  The default .exe or .dll file name is derived
  from the first file on the LINK command line.

ENVIRONMENT VARIABLE
  The contents of the environment variable WRILDFLAGS, if exported,
  will be added to the beginning of the command line.  This can give
  you some control over the behavior of the linker in automated
  build script situations.

EXTRANEOUS STUFF
  The configure script demands that the linker help output have the
  text auto-import somewhere in it, so here it is.
EOF

exit 0;
}

# When text is added to the LINK command line by the -Y option, see if it
# has the same meaning as one of the wrild command-line options.  If so,
# set the appropriate flags and variables.  For instance, passing /DLL
# to LINK is the same as the -G option, so set the op_dll flag that -G sets.
# It's important to do this when the flags are used to control other
# behavior.
#
# This function is quite incomplete and should handle many other LINK options.
function Check_For_Specials
{
	local param

	# Since we want to exclude the contents of strings from
	# our search for option names, we essentially delete strings.
	param=" ${1//\\\\?/?}"	# replace all escapes with ? first
	param="`echo \"$param\" | sed 's/\"[^\"]*\"/?/g'`"
				# now replace all quoted strings with ?
	# param is $1 with all quoted strings properly removed

	# Check for the /DLL flag
	if [ "${param/[ \t][-\/][dD][lL][lL]/q}" != "$param" ]; then
		op_dll=1
	fi
}

# Handle the -Y options.  These options let you pass arguments
# directly to LINK, the underlying Microsoft linker.  On entry,
# $1 contains the argument to the -Y option, that is, the portion
# following -Y.
function Parse_PassThrough_Options
{
	# Allowable syntax for the -Y option:
	#  -Yl,foo - add foo verbatim to the LINK options
	#  -YL,foo - add foo verbatim to the *end* of the LINK line

	# Note that if foo contains spaces, it is necessary to quote
	# it twice: once for the invocation of wrild, and again (\")
	# for the invocation of LINK.
	#    e.g. -Yl,"/I \"\Program Files\Wolfram Research\""
	# The outer quotes keep the argument of /Y together; the
	# inner ones make the /I path quoted on the cl command line.
	if [ x"${1#l,}" != x"$1" ]; then
		Check_For_Specials "${1#l,}"
		Append_To_Linkline "${1#l,}"
	elif [ x"${1#L,}" != x"$1" ]; then
		Check_For_Specials "${1#L,}"
		Append_To_LinkEnd "${1#L,}"
	else
		echo "Option $1: illegal -Y argument for wrild." >&2
		Fail_Usage
	fi
}

# Process the command line arguments.  This function iterates through
# all the arguments on the command line, and sets lots of variables.
# Each of the command-line options sets corresponding flags and
# string variables, indicating its content.  Filenames are stored
# into the o_flags array, unless they are singled out for special
# treatment based on their suffix.
function Process_Command_Line_Arguments
{
while [ $# -ne 0 ]; do
    arg="$1"
    nextarg="$2"
    if [ "${arg:0:1}" = "-" ]; then
	# the argument begins with a -.  option or set of options.
	optset="${arg#-}"		# strip off the leading -

	# now iterate through all the letters in optset
	while [ -n "$optset" ]; do
	    opt="${optset:0:1}"		# pull letter off the front
	    optset="${optset:1}"	# drop that letter from optset
	    let optshift=0
	    case "$opt" in
		B ) get_optarg
		    case "$optarg" in
			static|nodynamic|no-dynamic ) op_static=1 ;;
			dynamic|nostatic|no-static ) op_static=0 ;;
			* ) echo "-B$optarg: must be static, dynamic,"\
			    "nostatic, or nodynamic." >&2
		    	    Fail_Usage ;;
		    esac ;;
		G ) if [ -n "$optset" ] ; then
		        case "$optset" in
		            export-all-symbols )
				op_export_all=1 
				;;
		            * ) echo "Invalid DLL setting: -G$optset" >&2
		                Fail_Usage ;;
		        esac
		        optset=
		    else
		        op_dll=1
		    fi ;;
		L ) get_optarg
		    Append_To_Libdirs "$optarg" ;;
		M ) get_optarg
		    op_rtl="$optarg" ;;
		Q ) op_debugging_print=1
		    ;;  # -Q is the SOOPER SEKRIT DEBUGGING PRINT INFO flag
		T ) get_optarg
		    case "$optarg" in
			console|CONSOLE ) op_subsystem="CONSOLE" ;;
			windows|gui|WINDOWS|GUI ) op_subsystem="WINDOWS" ;;
			* ) echo "Invalid subsystem: -T$optarg: must be"\
			         "console or windows." >&2
			    Fail_Usage ;;
		    esac ;;
		V ) op_verbose=1 ;;
		W ) get_optarg
		    warnlevel=$optarg
		    case "$warnlevel" in
		        [0123] ) : ;;
		        * ) echo "-W$warnlevel: must be 0-3." >&2
		            Fail_Usage ;;
		    esac ;;
		Y ) get_optarg
		    Parse_PassThrough_Options "$optarg" ;;
		Z ) op_add_symtable=1 ;;

		e ) get_optarg
		    op_entry="$optarg" ;;
		g ) op_debug=1 ;;
		h ) Print_Help_And_Exit ;;
		l ) get_optarg
		    lib_files[$lib_file_count]="$optarg"
		    let lib_file_count=$lib_file_count+1 ;;
		    
		o ) get_optarg
		    outfile=$optarg ;;
		s ) get_optarg
		    sed_munge_outfile=$optarg ;;
		u ) get_optarg
		    Append_To_Linkline "-include:$1" ;;

		- ) case x"$optset" in
			x"export-all-symbols" )
			    op_export_all=1
			    ;;
			x"output-def" )
			    opt="${opt}${optset}"
			    optset=
			    get_optarg
			    op_def_name="$optarg"
			    op_create_def=1
			    ;;
			x"help" )
			    Print_Help_And_Exit ;;
			* ) echo "$scriptname: illegal option -$opt"
			    Fail_Usage ;;
			esac
			optset=
			;;

		* ) echo "$scriptname: illegal option -$opt"
		     Fail_Usage ;;
	    esac
	done	# with while loop handling multiple options in an argument

    else
	# The argument does not begin with a "-".  It's a filename.
	filename="$1"
	case "$filename" in
	    *.o|*.obj|*.lib|*.exp|*.res|*.OBJ|*.LIB|*.EXP|*.RES )
			o_files[$o_file_count]="$filename" 
			let o_file_count=$o_file_count+1 ;;
	    *.def|*.DEF ) Append_To_Linkline "-DEF:$filename" ;;
	    * ) echo "Bad filename: $filename" >&2
		Fail_Usage ;;
	esac

	let optshift=0
    fi

    # skip to next command-line argument.  if an option used up a
    # command-line argument (e.g. "-o foo.o"), then optshift=1 and
    # we shift twice
    shift $((optshift+1))
done	# with while loop handling all command-line arguments.
}

# End of subfunctions.

# begin the main portion of the wrild shell script.

scriptname="$0"

# Read all the command-line arguments and set lots of flags and
# variables based on them.  Everything past this point is just
# analyzing and translating the results.
#
# We invoke the function using eval in order to pass all
# arguments in WRILDFLAGS through the tokenizer, just as if
# they were entered on the command line.

cmdline="Process_Command_Line_Arguments $WRILDFLAGS $@"
eval "$cmdline"

# If a -s option was given, munge the output file name using that script.
if [ x"$sed_munge_outfile" != x"" ]; then
    outfile="`echo $outfile | sed -e "$sed_munge_outfile"`"
fi

# Examine the output file to see if it will be a DLL.
if [ x"${outfile%.[dD][lL][lL]}" != x"$outfile" ]; then
    op_dll=1
fi

# DLLs must be linked with Windows subsystem
if [ op_dll = 1 ]; then
    op_subsystem="WINDOWS"
fi

# Add the directories in the environment variable LIB to the list of
# directories to search for standard libraries.
libdirs="$libdirs$LIB"

# Determine if this is a 32-bit or 64-bit build, by looking at the
# header of CL.  Snip off the last bit of the first line, case-flatten it,
# and use it as a platform determiner.  (80x86, ia-64, amd64).  Set bit64 if
# this is a 64-bit build (the platform name ends in "64"), and set it to
# the platform name if so.
clplatform=`cl 2>&1 | dos2unix | head -1 | grep -E -o '[^[:space:]]+$' | tr [A-Z] [a-z]`
if [ x"${clplatform%64}" != x"$clplatform" ]; then
    bit64="$clplatform"
else
    bit64=
fi

# Determine whether to build a 32-bit or 64-bit binary.
# Of course this must match the object files, or LINK will choke.
if [ x"$bit64" = x"ia-64" ]; then
    Append_To_Linkline "/MACHINE:IA64"
elif [[ (x"$bit64" = x"amd64") || (x"$bit64" = x"x64") ]]; then
    Append_To_Linkline "/MACHINE:AMD64"
else
    Append_To_Linkline "/MACHINE:I386"
fi

# If debugging, add debug flags to command line.
if [ $op_debug = 1 ]; then
	Append_To_Linkline "/DEBUG:FULL /DEBUGTYPE:CV"
fi

# Set subsystem.
Append_To_Linkline "/SUBSYSTEM:$op_subsystem"

# Set warning level, if any.
if [ -n "$warnlevel" ]; then
	Append_To_Linkline "/WARN:$warnlevel"
fi

# Set entry point, if any.  (If none specified, linker will determine it.)
if [ -n "$op_entry" ]; then
	Append_To_Linkline "/ENTRY:$op_entry"
fi

# If an output file name was specified, use it.
if [ -n "$outfile" ]; then
	Append_To_Linkline "/OUT:$outfile"
fi

# If building a DLL, add /DLL option.
if [ $op_dll = 1 ]; then
	Append_To_Linkline "/DLL"
fi

# Any files to link?
if [ $o_file_count -eq 0 ]; then
	echo "No files to link!" >&2
	Fail_Usage
fi

# Time to link!
# First put together a list of all files, and construct the LINK invocation.
allfiles=
for i in "${o_files[@]}"; do	# String together all the object files
	allfiles="$allfiles \"$i\""
done

# If we want to export all symbols in a DLL, we must run dlltool
# over the files to construct a .DEF file containing all the symbols.
if [ $op_export_all = 1 -o $op_create_def = 1 ]; then
	# Find the directory where the output file will be generated
	# We'll put the .DEF file there too.  Also make up a name for
	# the DEF file by snipping the extension off the output file
	# unless it's already been given.
	if [ -n "$op_def_name" ]; then
		deffile="$op_def_name"
	else
		if [ -n "$outfile" ]; then
			defpath="`dirname \"$outfile\"`"
			defname="`basename \"$outfile\"`"
		else
			# Guess at the output file name if it's not given.
			defpath='.'
			defname="${o_files[0]}"
		fi
		defname="${defname%.*}.def"
		deffile="$defpath/$defname"
	fi

	if [ -n "$bit64" ]; then

		# There's no dlltool for Win64.  Instead, we'll run our
		# 64-bit nm clone, then use a sed script to munge the output
		# into DEF file syntax.

		# TODO: Can we create a DEF file without exporting all symbols?
		# Neither wri-nm-64 nor DUMPBIN really give you a way to
		# separate the dllexported ones from the rest.  So for now, we
		# always export all symbols if we make a .DEF file...

		cmdline="wri-nm-64 --format=posix --extern-only $allfiles > \"$deffile\""
		if [ $op_verbose = 1 ]; then
			echo "$cmdline"
		fi
		eval "$cmdline"
		es=$?
		if [ $es != "0" ]; then
			exit $es	# WRI-NM-64 failed!
		fi

		# Convert the output of wri-nm-64 to a proper DEF file.
		mv "$deffile" "$deffile.bak"
		echo EXPORTS > "$deffile"

		# Find the sed script we want to use.  It's in the same
		# directory as this script.
		script_dir=`dirname "${0}"`
		script_dir=`cd "${script_dir}"; pwd`

		cmdline="sed -f $script_dir/wri-nm2def.sed \"$deffile.bak\" >> \"$deffile\""
		if [ $op_verbose = 1 ]; then
			echo "$cmdline"
		fi
		eval "$cmdline"
		es=$?
		if [ $es != "0" ]; then
			exit $es	# SED failed!
		fi

	else

		# dlltool's -z option generates a .DEF file
		if [ $op_export_all ]; then
			EAS="--export-all-symbols"
		else
			EAS=
		fi
		cmdline="dlltool -z \"$deffile\" $EAS $allfiles"
		if [ $op_verbose = 1 ]; then
			echo "$cmdline"
		fi
		eval "$cmdline"
		es=$?
		if [ $es != "0" ]; then
			exit $es	# DLLTOOL failed!
		fi

		# Remove nonsense lines from .DEF file
		mv "$deffile" "$deffile.bak"
		grep -v "^;" "$deffile.bak" | \
			grep -v "^[[:blank:]]*_real@" | \
			grep -v "^[[:blank:]]*??_" \
				 > "$deffile"

		# Remove ordinals from .DEF file lines
		mv "$deffile" "$deffile.bak"
		sed -e 's/@ [0-9]* *//' "$deffile.bak" > "$deffile"

	fi

	# Now add that .DEF file to the link
	# TODO: not if a .def file was specified on the command line
	Append_To_Linkline "/DEF:\"$deffile\""
fi

cmdline="\"$LD\" $linkline"
cmdline="$cmdline $allfiles $linkend"

save_LIB=$LIB	# Save LIB variable
LIB=$libdirs
if [ $op_verbose = 1 ]; then
	echo "LIB=$LIB"
	echo "$cmdline"
fi
eval "$cmdline"	# Perform the LINK
retval=$?	# Save the exit status
LIB=$save_LIB	# Restore LIB variable
if [ $retval != "0" ]; then
	exit $retval	# LINK failed!
fi

if [ $op_debugging_print = 1 ]; then
echo "------------------------------------------------------------------------"

echo "Here are the files."
echo "Object files (o_file_count=$o_file_count):"
for i in "${o_files[@]}"; do
	echo $i
done
echo "Library files (lib_file_count=$lib_file_count):"
for i in "${lib_files[@]}"; do
	echo $i
done
echo ""

echo "No complications, only some options:"
echo "op_static=$op_static"
echo "op_debug=$op_debug"
echo "op_verbose=$op_verbose"
echo "op_rtl=$op_rtl"
echo "op_symtable=$op_symtable"
echo "op_entry=$op_entry"
echo "op_subsystem=$op_subsystem"
echo "op_dll=$op_dll"
echo "op_export_all=$op_export_all"
echo "op_symtable=$op_symtable"
echo "warnlevel=$warnlevel"
echo "sed_munge_outfile=$sed_munge_outfile"

echo "outfile=$outfile"
echo "deffile=$deffile"

echo "linkline=$linkline"
echo "linkend=$linkend"
echo "libdirs=$libdirs"
echo "------------------------------------------------------------------------"
fi  # $op_debugging_print = 1

exit 0;








# Copyright 2010 Wolfram Research, Inc.
#
# This file is part of the build scripts for building the GNU MP Library
# for Mathematica on Windows (32-bit).
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see http://www.gnu.org/licenses/.
