#!/bin/sh
#
# Shell command language linker
#
# Copyright (C) 2015 Patrick "P. J." McDermott
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
set -u
VERSION='0.2.0'
die()
{
local fmt="${1}"
shift 1
printf "shld: ${fmt}\n" "${@}" >&2
exit 2
}
link()
{
local make_executable="${1}"
local interpreter="${2}"
local entry_point="${3}"
local output="${4}"
shift 4
local input=
# Open output file.
if ! exec 3>"${output}~"; then
die 'Cannot open file "%s"' "${output}~"
fi
# Write magic number and interpreter path.
if ${make_executable}; then
printf '#!%s\n' "${interpreter}" >&3
fi
# Write __init() function.
cat >&3 <<-'EOF'
__init_funcs=''
__init()
{
__init_funcs="${__init_funcs} ${1}"
}
EOF
# Read input files.
for input in "${@}"; do
if ! cat "${input}" >&3; then
die 'Cannot read file "%s"' "${input}"
fi
done
# Add call to init functions.
cat >&3 <<-'EOF'
for __func in ${__init_funcs}; do
${__func}
done
EOF
# Add call to entry point.
if ${make_executable}; then
printf '%s "${@}"\n' "${entry_point}" >&3
fi
# Close output file, make it executable, and set its name.
exec 3>&-
if ${make_executable}; then
if ! chmod a+x "${output}~"; then
die 'Cannot set mode of file "%s"' "${output}~"
fi
fi
if ! mv "${output}~" "${output}"; then
die 'Cannot rename file to "%s"' "${output}"
fi
}
usage()
{
printf 'Usage: %s [option ...] ...\n' "${0}"
}
help()
{
usage
cat < Make an executable and use as the interpreter for your
program, instead of the default of "/bin/sh"
-e Make an executable and use as the function for beginning
execution of your program, instead of the default of "main"
-o