#!/bin/sh

SELF="$( basename $0 )"
VERSION="0.0.1"

# default executable filename
EXE="a.out"

# default plic options. -ewd makes it exit with 0 status if there
# were warnings, and print its warnings to stderr where we can see them.
OPTS="-ewd"

# default to non-verbose. --verbose sets this to 1.
V=0

usage() {
  if ! type -p perldoc; then
    echo "$SELF: can't find perldoc on PATH, printing raw POD." 1>&2
    exec sed -n '/^=pod/,/^=cut/p' $0
  fi

  exec perldoc "$0"
}

manpage() {
  exec pod2man --stderr -s1 -c"PL/I Support" -r$VERSION "$0"
}

# this really should check for tabs and newline, too...
check_spaces() {
  case "$1" in
    *' '*) echo "$SELF: input filenames may not contain spaces." 1>&2
           exit 1 ;;
  esac
}

while [ -n "$1" ]; do
  case "$1" in
    --verbose) V=1 ;;
    --help) usage; exit 0 ;;
    --man)  manpage; exit 0 ;;
    -c|-C)  C=1; EXE="" ;;
    -o)     O=1; EXE="$2"; shift ;;
    -o*)    O=1; EXE="$( printf "%s" "$1" | sed 's,^-o,,' )" ;;
    -*)     OPTS="$OPTS $1" ;;
    *.o)    check_spaces "$1"; OBJS="$OBJS $1" ;;
    *)      check_spaces "$1"; SRCS="$SRCS $1"
            OBJS="$OBJS $( printf "%s" "$1" | sed 's,\(\.[^.]*\)\?$,.o,' )"
            ;;
  esac
  shift
done

if [ "$C" = "1" -a "$O" = "1" ]; then
  echo "$SELF: -o option not allowed in combination with -c." 1>&2
  exit 1
fi

if [ "$V" = "1" ]; then
  echo "EXE: $EXE"
  echo "SRCS: $SRCS"
  echo "OBJS: $OBJS"
  echo "OPTS: $OPTS"
fi

if [ -z "$OBJS" ]; then
  echo "$SELF: fatal error: no input files. Try '$SELF --help'." 1>&2
  exit 1
fi

if [ -z "$EXE" -a -z "$SRCS" ]; then
  echo "$SELF: nothing to do (-c used, but no source files given)." 1>&2
  exit 1
fi

for i in $SRCS; do
  set -e
  if [ "$V" = "1" ]; then
    echo "Compiling '$i'"
    set -x
  fi

  # annoying: there's no way to make plic exit non-zero if the
  # input file wasn't found (though it will, if there were compile errors).
  if [ ! -r "$i" ]; then
    echo "$SELF: Input file not found or not readable: '$i'." 1>&2
    exit 1
  fi

  ${PLIC:-plic} -C $OPTS "$i"
  set +x
done

if [ -n "$EXE" ]; then
  if [ "$V" = "1" ]; then
    echo "Linking '$EXE'"
    set -x
  fi

  # adapted from SA_make in the pli distribution.
  ${LD:-ld} -z muldefs -Bstatic -M -e main -t \
     -o "$EXE" \
     $OBJS \
     --oformat=elf32-i386 -melf_i386 -lprf $LIBS > "$EXE".map

  X="$?"
  set +x
  [ "$V" = "1" ] && echo "Linker exit status: $X"
  exit $X
fi

exit 0

# Rest of the file is perldoc.
: <<EOF
=pod

=head1 NAME

B<plicl> - compile and link PL/I programs

=head1 SYNOPSIS

B<plicl> [--verbose] -c [plic-options] input-file [input-file ...]

B<plicl> [--verbose] -o output-file [plic-options] input-file [input-file ...]

B<plicl> [--man | --help | --version]

=head1 DESCRIPTION

B<plicl> (rhymes with I<pickle>) is a wrapper script for B<plic>(1)
(the Iron Spring PL/I compiler) and B<ld>(1) (the GNU linker, at least
on most Linux systems). It allows you to compile PL/I code from the
command line without having to create a Makefile or manually execute
separate compile and link commands.

Input files may be any combination of PL/I source or object files
already compiled by B<plic>.

By default (without B<-c>) all source files are compiled and linked
together with any object files, to create an executable named "a.out"
by default. Use the B<-o> option to give the executable a different
name.

B<plicl> is deliberately kept simple. If you have a PL/I project that's
too complex for B<plicl>, you should be using B<plic> and ld directly, with
a Makefile such as the SA_make that's distributed with the compiler.

B<plicl> can't handle input filenames with spaces in them,
though spaces are OK in the outfile filename. Filenames with shell
metacharacters may or may not work if quoted properly; they're best
avoided.

=head1 OPTIONS

All options other than B<-c>, B<-o>, B<--verbose>, B<--man>, and
B<--help> are passed as-is to B<plic>.

=over

=item B<-c>

Compile only; do not link. Each PL/I source file is compiled to an
object file. The B<-o> option is not allowed when using B<-c>; object
file names are based on the source file names, with the extension
changed to ".o". Any object files given as arguments are ignored.

=item B<-o>

Set output executable's filename. By default, this is I<a.out>. This
option only makes sense to use when linking an executable, so it's not
valid when B<-c> is used.

=item B<--verbose>

Print some (possibly) useful information about what what B<plicl> is doing.

=item B<--help>

Print this help to standard output and exit. Since the help is long,
it will be passed through your pager.

=item B<--man>

Print this help in man page (troff) format to standard output and exit.

=back

=head1 ENVIRONMENT

=over

=item B<PLIC>

Set the path to the PL/I compiler. By default, this is I<plic>, which
will be searched for in B<PATH>. This could be set to an absolute
path, e.g. if you had multiple versions of B<plic> installed and
wanted to choose between them.

=item B<LD>

Set the path to the linker. By default, this is I<ld>, which will
be searched for in B<PATH>. Has no meaning if B<-c> option is used.

=item B<LIBS>

Additional libraries to link the executable with. Default is
empty. This could be set to e.g. B<LIBS=-lpbl> to link the ISAM
library, or something like B<LIBS="foo.a bar.a"> to link with a
library you've created with B<ar>(1). Has no meaning if B<-c> option is used.

=back

=head1 EXAMPLES

  # compile and link a single PL/I source file into an executable:
  plicl -o hello hello.pli

  # compile and link multiple PL/I source files into an executable:
  plicl -o foobarbaz foo.pli bar.pli baz.pli

  # compile all PL/I source files in the current directory to objects:
  plicl -c *.pli

  # link all the object files in the current directory to create an executable:
  plicl -o my_executable *.o

=head1 AUTHOR

B<plicl> was written by B. Watson (yalhcru@gmail.com).

=head1 COPYRIGHT

B<plicl> is licensed under the WTFPL: do WTF you want to with this.
See http://www.wtfpl.net/txt/copying/ for details.

=cut
EOF