blob: fa9f6095d327607dda6d6840f80236823f162255 [file] [log] [blame]
#! /bin/sh -e
#
# COPYRIGHT
# The gcobc program is in public domain.
# If it breaks then you get to keep both pieces.
#
# This file emulates the GnuCOBOL cobc compiler to a limited degree.
# For options that can be "mapped" (see migration-guide.1), it accepts
# cobc options, changing them to the gcobol equivalents. Options not
# recognized by the script are passed verbatim to gcobol, which will
# reject them unless of course they are gcobol options.
#
# User-defined variables, and their defaults:
#
# Variable Default Effect
# echo none If defined, echo the gcobol command
# gcobcx none Produce verbose messages
# gcobol ./gcobol Name of the gcobol binary
# GCOBCUDF PREFIX/share/cobol/udf/ Location of UDFs to be prepended to input
#
# By default, this script includes all files in $GCOBCUDF. To defeat
# that behavior, use GCOBCUDF=none.
#
# A list of supported options is produced with "gcobc -HELP".
#
## Maintainer note. In modifying this file, the following may make
## your life easier:
##
## - To force the script to exit, either set exit_status to 1, or call
## the error function.
## - As handled options are added, add them to the HELP here-doc.
## - The compiler can produce only one kind of output. In this
## script, that's known by $mode. Options that affect the type of
## output set the mode variable. Everything else is appended to the
## opts variable.
##
## - -fPIC is added to the command line if $mode is "-shared". That
## option applies only to "certain machines", per the gcc info
## manual. For this script to be portable across machines, -fPIC
## would have to be set more judiciously.
if [ "$COBCPY" ]
then
copydir="-I$COBCPY"
fi
if [ "$COB_COPY_DIR" ]
then
copydir="-I$COB_COPY_DIR"
fi
# TODO: this file likely needs to query gcobol for its shared path instead
udf_default="${0%/*}/../share/gcobol/udf"
if [ ! -d "$udfdir" ]
then
# the one above is the installed one from the packages this one was previously used
udf_default="${0%/*}/../share/cobol/udf"
fi
udfdir="${GCOBCUDF:-$udf_default}"
if [ -d "$udfdir" ]
then
for F in "$udfdir"/*
do
if [ -f "$F" ]
then
includes="$includes -include $F "
fi
done
else
if [ "${GCOBCUDF:-none}" != "none" ]
then
echo warning: no such directory: "'$GCOBCUDF'"
fi
fi
exit_status=0
skip_arg=
opts="$copydir $includes"
mode=-shared
incomparable="has no comparable gcobol option"
if [ "${gcobcx:-0}" -gt 1 ]
then
set -x
fi
error() {
echo "error: $1" >&2
exit_status=1
}
warn() {
echo "warning: $1 ignored" >&2
}
ignore_arg() {
warn "$1"
skip_arg="$1"
}
no_warn() { :; } # silence is golden
help() {
cat<<EOF
$0 recognizes the following GnuCOBOL cobc output mode options:
-b, -c, -m, -S, -x
$0 recognizes the following GnuCOBOL cobc compilation options:
-C
-d, --debug
-D
-A
-Q
-E
-g
--coverage
-ext
-fec=exception-name, -fno-ec=exception-name
-fformat
--fixed
-F, --free
-fimplicit-init
-h, --help
-save-temps=
-save-temps
-std=mvs -std=mvs-strict
-std=mf -std=mf-strict
-std=cobol85 -std=cobol2002 -std=cobol2014
Options that are the same in gcobol and cobc are passed through verbatim.
Options that have no analog in gcobol produce a warning message.
To produce this message, use -HELP.
To see the constructed cobc command-line, use -echo.
To override the default cobc, set the "cobc" environment variable.
By default, gcobc invokes the gcobol the same directory the gcobc resides.
To override, set the gcobol environment variable.
EOF
}
dialect="mf gnu"
out_set=""
first=""
#
# Iterate over the command-line tokens. We can't use getopts here
# because it's not designed for single-dash words (e.g. -shared).
#
for opt in "$@"
do
if [ "$skip_arg" ]
then
skip_arg=
continue
fi
if [ "$pending_arg" ]
then
case $pending_arg in
-o) output_name="$opt" # capture named output file
;;
esac
opts="$opts $pending_arg$opt"
pending_arg=
continue
fi
case $opt in
# pass next parameter to GCC
-A)
pending_arg=" "
;;
# pass next parameter to linker
-Q)
pending_arg=-Wl,
;;
-b) mode="-shared"
;;
-c) mode="-c"
;;
--conf=*) warn "$opt"
;;
-C) error "$opt $incomparable"
;;
-d | -debug | --debug) opts="$opts -fcobol-exceptions=EC-ALL"
warn "$opt implies -fstack-check:"
;;
# define for preprocessor, note: -D* is directly passed
-D)
pending_arg=$opt
;;
-E) opts="$opts $opt -fsyntax-only"
;;
-echo) echo="echo"
;;
-fec=* | -fno-ec=*)
opt="$(echo "$opt" | sed -E 's/-f(no-)?ec=/-f\1cobol-exceptions=EC-/g')"
opts="$opts $opt"
;;
-ext)
pending_arg="$opt "
;;
-ext=*) opts="$opts $(echo "$opt" | sed 's/-ext=/-copyext ./')"
;;
# A.3 Compiler options
-fsign=*) warn "$opt" ;;
-ffold-copy=*) warn "$opt" ;;
-ffold-call=*) warn "$opt" ;;
-fmax-errors=*) warn "$opt" ;;
-fintrinsics=*) warn "$opt" ;;
-fdump=*) warn "$opt" ;;
-fcallfh=*) warn "$opt" ;;
-fsqlschema=*) warn "$opt" ;;
-fsql) warn "$opt" ;;
-fno-recursive-check) no_warn "$opt" ;;
-fstack-extended) warn "$opt" ;;
-fno-remove-unreachable) no_warn "$opt" ;;
-finline-intrinsic) warn "$opt" ;;
-ftrace) warn "$opt" ;;
-ftraceall) warn "$opt" ;;
-fsymtab) warn "$opt" ;;
# -fsyntax-only is identical
-fdebugging-line) warn "$opt" ;;
-fsource-location) warn "$opt" ;;
-fstack-check) warn "$opt" ;;
-fsection-exit-check) warn "$opt" ;;
-fimplicit-goback-check) warn "$opt" ;;
-fwrite-after) warn "$opt" ;;
-fmfcomment) warn "$opt" ;;
-facucomment) warn "$opt" ;;
-fno-trunc) no_warn "$opt" ;;
-fsingle-quote) warn "$opt" ;;
-foptional-file) warn "$opt" ;;
-fstatic-call | -fno-static-call)
opts="$opts $opt"
static_used="x"
;;
-fno-gen-c-decl-static-call) no_warn "$opt" ;;
-fmf-files) warn "$opt" ;;
-ffile-format=*) warn "$opt" ;;
-fno-theaders) no_warn "$opt" ;;
-fno-tsource) no_warn "$opt" ;;
-fno-tmessages) no_warn "$opt" ;;
-ftsymbols) warn "$opt" ;;
-fdatamap) warn "$opt" ;;
-fno-diagnostics-show-option) no_warn "$opt" ;;
-fibmcomp) warn "$opt" ;;
-fno-ibmcomp) no_warn "$opt" ;;
# A.4 Compiler dialect configuration options
-fname=*) warn "$opt" ;;
-freserved-words=*) warn "$opt" ;;
-ftab-width=*) warn "$opt" ;;
-ftext-column=*) warn "$opt" ;;
-fpic-length=*) warn "$opt" ;;
-fword-length=*) warn "$opt" ;;
-fliteral-length=*) warn "$opt" ;;
-fnumeric-literal-length=*) warn "$opt" ;;
-fdefaultbyte=*) warn "$opt" ;;
-falign-record=*) warn "$opt" ;;
-fkeycompress=*) warn "$opt" ;;
-falign-opt) warn "$opt" ;;
-fbinary-size=*) warn "$opt" ;;
-fbinary-byteorder=*) warn "$opt" ;;
-fassign-clause=*) warn "$opt" ;;
-fscreen-section-rules=*) warn "$opt" ;;
-fdpc-in-data=*) warn "$opt" ;;
-ffilename-mapping) warn "$opt" ;;
-fpretty-display) warn "$opt" ;;
-fbinary-truncate | -fno-binary-truncate) warn "$opt" ;;
-fcomplex-odo) warn "$opt" ;;
-fodoslide) warn "$opt" ;;
-findirect-redefines) warn "$opt" ;;
-flarger-redefines-ok) warn "$opt" ;;
-frelax-syntax-checks) warn "$opt" ;;
-fref-mod-zero-length) warn "$opt" ;;
-frelax-level-hierarchy) warn "$opt" ;;
-flocal-implies-recursive) warn "$opt" ;;
-fsticky-linkage) warn "$opt" ;;
-fmove-ibm) warn "$opt" ;;
-fperform-osvs) warn "$opt" ;;
-farithmetic-osvs) warn "$opt" ;;
-fconstant-folding) warn "$opt" ;;
-fhostsign) warn "$opt" ;;
-fprogram-name-redefinition) warn "$opt" ;;
-faccept-update) warn "$opt" ;;
-faccept-auto) warn "$opt" ;;
-fconsole-is-crt) warn "$opt" ;;
-fno-echo-means-secure) no_warn "$opt" ;;
-fline-col-zero-default) warn "$opt" ;;
-freport-column-plus) warn "$opt" ;;
-fdisplay-special-fig-consts) warn "$opt" ;;
-fbinary-comp-1) warn "$opt" ;;
-fnumeric-pointer) warn "$opt" ;;
-fmove-non-numeric-lit-to-numeric-is-zero) warn "$opt" ;;
-fimplicit-assign-dynamic-var) warn "$opt" ;;
-fcomment-paragraphs=*) warn "$opt" ;;
-fmemory-size-clause=*) warn "$opt" ;;
-fmultiple-file-tape-clause=*) warn "$opt" ;;
-flabel-records-clause=*) warn "$opt" ;;
-fvalue-of-clause=*) warn "$opt" ;;
-fdata-records-clause=*) warn "$opt" ;;
-ftop-level-occurs-clause=*) warn "$opt" ;;
-fsame-as-clause=*) warn "$opt" ;;
-ftype-to-clause=*) warn "$opt" ;;
-fusage-type=*) warn "$opt" ;;
-fsynchronized-clause=*) warn "$opt" ;;
-fsync-left-right=*) warn "$opt" ;;
-fspecial-names-clause=*) warn "$opt" ;;
-fgoto-statement-without-name=*) warn "$opt" ;;
-fstop-literal-statement=*) warn "$opt" ;;
-fstop-identifier-statement=*) warn "$opt" ;;
-fdebugging-mode=*) warn "$opt" ;;
-fuse-for-debugging=*) warn "$opt" ;;
-fpadding-character-clause=*) warn "$opt" ;;
-fnext-sentence-phrase=*) warn "$opt" ;;
-flisting-statements=*) warn "$opt" ;;
-ftitle-statement=*) warn "$opt" ;;
-fentry-statement=*) warn "$opt" ;;
-fmove-noninteger-to-alphanumeric=*) warn "$opt" ;;
-foccurs-max-length-without-subscript) warn "$opt" ;;
-flength-in-data-division) warn "$opt" ;;
-fmove-figurative-constant-to-numeric=*) warn "$opt" ;;
-fmove-figurative-space-to-numeric=*) warn "$opt" ;;
-fmove-figurative-quote-to-numeric=*) warn "$opt" ;;
-fodo-without-to=*) warn "$opt" ;;
-fodo-last-varlen=*) warn "$opt" ;;
-fsection-segments=*) warn "$opt" ;;
-falter-statement=*) warn "$opt" ;;
-fcall-overflow=*) warn "$opt" ;;
-fnumeric-boolean=*) warn "$opt" ;;
-fhexadecimal-boolean=*) warn "$opt" ;;
-fnational-literals=*) warn "$opt" ;;
-fhexadecimal-national-literals=*) warn "$opt" ;;
-fnational-character-literals=*) warn "$opt" ;;
-fhp-octal-literals=*) warn "$opt" ;;
-facu-literals=*) warn "$opt" ;;
-fword-continuation=*) warn "$opt" ;;
-fnot-exception-before-exception=*) warn "$opt" ;;
-faccept-display-extensions=*) warn "$opt" ;;
-frenames-uncommon-levels=*) warn "$opt" ;;
-fsymbolic-constant=*) warn "$opt" ;;
-fconstant-78=*) warn "$opt" ;;
-fconstant-01=*) warn "$opt" ;;
-fperform-varying-without-by=*) warn "$opt" ;;
-freference-out-of-declaratives=*) warn "$opt" ;;
-freference-bounds-check=*) warn "$opt" ;;
-fprogram-prototypes=*) warn "$opt" ;;
-fcall-convention-mnemonic=*) warn "$opt" ;;
-fcall-convention-linkage=*) warn "$opt" ;;
-fnumeric-value-for-edited-item=*) warn "$opt" ;;
-fincorrect-conf-sec-order=*) warn "$opt" ;;
-fdefine-constant-directive=*) warn "$opt" ;;
-ffree-redefines-position=*) warn "$opt" ;;
-frecords-mismatch-record-clause=*) warn "$opt" ;;
-frecord-delimiter=*) warn "$opt" ;;
-fsequential-delimiters=*) warn "$opt" ;;
-frecord-delim-with-fixed-recs=*) warn "$opt" ;;
-frecord-sequential-advancing=*) warn "$opt" ;;
-fmissing-statement=*) warn "$opt" ;;
-fzero-length-literals=*) warn "$opt" ;;
-fxml-generate-extra-phrases=*) warn "$opt" ;;
-fcontinue-after=*) warn "$opt" ;;
-fgoto-entry=*) warn "$opt" ;;
-fdepending-on-not-fixed=*) warn "$opt" ;;
-fbinary-sync-clause=*) warn "$opt" ;;
-fnonnumeric-with-numeric-group-usage=*) warn "$opt" ;;
-fassign-variable=*) warn "$opt" ;;
-fassign-using-variable=*) warn "$opt" ;;
-fassign-ext-dyn=*) warn "$opt" ;;
-fassign-disk-from=*) warn "$opt" ;;
-fvsam-status=*) warn "$opt" ;;
-fself-call-recursive=*) warn "$opt" ;;
# TODO: create a temporary COBOL file with COBOL-WORDS directives
# and force-include it
-fnot-reserved=*) warn "$opt" ;;
-freserved=*) warn "$opt" ;;
-fnot-register=*) warn "$opt" ;;
-fregister=*) warn "$opt" ;;
-fformat=auto) ;; # gcobol and gnucobol default
-fixed | --fixed | -fformat=fixed | -fformat=variable | -fformat=xcard)
# note: variable + xcard are only _more similar_ to fixed than free,
# (with changing right-column to 250/255, which isn't supported in gcobol, yet)
opts="$opts -ffixed-form"
;;
-F | -free | --free | -fformat=free | -fformat=*)
# note: "all other formats" are only _more similar_ to free than fixed
opts="$opts -ffree-form"
;;
-h | --help) opts="$opts --help"
;;
-HELP) help && exit
;;
-i | --info) warn "$opt"
;;
# -I
-fimplicit-init) warn "$opt"
;;
-j | -job) warn "$opt"
;;
-K) ignore_arg "$opt"
;;
-K*) warn "$opt"
;;
# -l
# -L
--list*) warn "$opt"
;;
-m) mode="-shared"
;;
# -main
# -nomain
-o) pending_arg=$opt
;;
-o*) output_name=$opt ## non-empty means do not infer
opts="$opts $opt"
;;
# -O0, -Ox
-O | -O2 | -Os) warn "$opt"
;;
-S) mode="$opt"
;;
-save-temps=*) opt="$(echo "$opt" | sed -E 's/^.+=//')"
export GCOBOL_TEMPDIR="$opt"
;;
-save-temps) export GCOBOL_TEMPDIR="${PWD:-$(pwd)}"
;;
# -shared is identical
-std=mvs | -std=mvs-strict | -std=ibm | -std=ibm-strict) dialect=ibm
;;
-std=mf | -std=mf-strict) dialect=mf
;;
# GnuCOBOL's default and GCC's dialect for GnuCOBOL
-std=default) dialect=gnu
;;
# GCC COBOL targets COBOL2024 "mostly backward to COBOL85"
-std=cobol*) dialect=""
;;
-std=*)
dialect=""
warn "$opt (unkown dialect)"
;;
-P | -P=* | -X | --Xref)
warn "$opt (no listing)"
;;
-t | -T)
# note: -P has an _optional_ arg, so we leave it above
ignore_arg "$opt (no listing)"
;;
-q | --brief) warn "$opt"
;;
-v | --verbose) opts="$opts -V"
;;
# note: we want -dumpversion to be passed to gcc
-V | --version | -version) opts="$opts --version"
;;
# pass through, strangely -Wall is not supported
-w | -W | -Wextra) opts="$opts $opt"
;;
-Wno-*) no_warn "$opt"
;;
-W*) ignore_arg "$opt"
;;
-x) mode=
;;
-) output_name=a.out # nonnull to prevent overriding gcc default
opts="$opts /dev/stdin"
;;
# First file name argument is default output filename.
*) if [ -z "$output_name" -a -e "$opt" ]
then
output_name=$(basename "${opt%.*}")
case $mode in
-c) output_name="$output_name".o
;;
-shared)
output_name="$output_name".so
opts="$opts -fPIC"
;;
esac
opts="$opts -o $output_name"
fi
opts="$opts $opt" # pass through
;;
esac
done
# cobc default:
if [ "$static_used" = "" ]
then
opts="$opts -fno-static-call";
fi
if [ "$exit_status" -gt 0 ]
then
exit $exit_status
fi
# To override the default gcobol, set the "gcobol" environment variable.
gcobol="${gcobol:-${0%/*}/gcobol}"
if [ "$dialect" ]
then
dialect=$(echo $dialect | sed -E 's/[[:alnum:]]+/-dialect &/g')
fi
if [ "$echo" ]
then
echo $gcobol $mode $opts
exit
fi
if [ "$gcobcx" ]
then
set -x
fi
exec $gcobol $mode $dialect $opts