view src/mkoctfile.in.cc @ 31771:21f9b34eb893

maint: Eliminate "(void)" in C++ function prototypes/declarations. * mk-opts.pl, external.txi, embedded.cc, make_int.cc, standalone.cc, standalonebuiltin.cc, BaseControl.cc, BaseControl.h, ButtonControl.cc, ButtonControl.h, ButtonGroup.cc, ButtonGroup.h, Canvas.cc, Canvas.h, CheckBoxControl.cc, CheckBoxControl.h, Container.cc, Container.h, ContextMenu.cc, ContextMenu.h, EditControl.cc, EditControl.h, Figure.cc, Figure.h, FigureWindow.cc, FigureWindow.h, GLCanvas.cc, GLCanvas.h, GenericEventNotify.h, KeyMap.cc, ListBoxControl.cc, ListBoxControl.h, Logger.cc, Logger.h, Menu.cc, Menu.h, MenuContainer.h, Object.cc, Object.h, ObjectProxy.cc, ObjectProxy.h, Panel.cc, Panel.h, PopupMenuControl.cc, PopupMenuControl.h, PushButtonControl.cc, PushButtonControl.h, PushTool.cc, PushTool.h, RadioButtonControl.cc, RadioButtonControl.h, SliderControl.cc, SliderControl.h, Table.cc, Table.h, TextControl.cc, TextControl.h, TextEdit.h, ToggleButtonControl.cc, ToggleButtonControl.h, ToggleTool.cc, ToggleTool.h, ToolBar.cc, ToolBar.h, ToolBarButton.cc, ToolBarButton.h, gl-select.cc, gl-select.h, qopengl-functions.h, qt-graphics-toolkit.h, qdialog.cpp, qfontdialog.cpp, qprintdialog_win.cpp, liboctgui-build-info.h, liboctgui-build-info.in.cc, color-picker.cc, color-picker.h, command-widget.cc, command-widget.h, community-news.cc, community-news.h, dialog.cc, dialog.h, documentation-bookmarks.cc, documentation-bookmarks.h, documentation-dock-widget.cc, documentation-dock-widget.h, documentation.cc, documentation.h, dw-main-window.cc, dw-main-window.h, external-editor-interface.cc, external-editor-interface.h, files-dock-widget.cc, files-dock-widget.h, find-files-dialog.cc, find-files-dialog.h, find-files-model.cc, find-files-model.h, gui-preferences.cc, gui-preferences.h, gui-settings.cc, gui-settings.h, history-dock-widget.cc, history-dock-widget.h, interpreter-qobject.cc, interpreter-qobject.h, file-editor-interface.h, file-editor-tab.cc, file-editor-tab.h, file-editor.cc, file-editor.h, find-dialog.cc, find-dialog.h, marker.cc, marker.h, octave-qscintilla.cc, octave-qscintilla.h, octave-txt-lexer.cc, octave-txt-lexer.h, main-window.cc, main-window.h, news-reader.cc, news-reader.h, octave-dock-widget.cc, octave-dock-widget.h, octave-qobject.cc, octave-qobject.h, qt-application.cc, qt-application.h, qt-interpreter-events.cc, qt-interpreter-events.h, release-notes.cc, release-notes.h, set-path-dialog.cc, set-path-dialog.h, set-path-model.cc, set-path-model.h, settings-dialog.cc, settings-dialog.h, shortcuts-tree-widget.cc, shortcuts-tree-widget.h, tab-bar.cc, tab-bar.h, terminal-dock-widget.cc, terminal-dock-widget.h, variable-editor-model.cc, variable-editor-model.h, variable-editor.cc, variable-editor.h, welcome-wizard.cc, welcome-wizard.h, workspace-model.cc, workspace-model.h, workspace-view.cc, workspace-view.h, build-env.h, Cell.cc, Cell.h, __contourc__.cc, __magick_read__.cc, auto-shlib.cc, auto-shlib.h, base-text-renderer.h, bsxfun.cc, c-file-ptr-stream.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, debug.cc, defaults.cc, defaults.h, defun.cc, display.cc, display.h, dynamic-ld.cc, dynamic-ld.h, environment.cc, environment.h, error.cc, error.h, errwarn.cc, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, ft-text-renderer.cc, ft-text-renderer.h, genprops.awk, gh-manager.cc, gh-manager.h, gl-render.cc, gl-render.h, gl2ps-print.cc, graphics-toolkit.h, graphics.cc, graphics.in.h, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, jsondecode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, ls-hdf5.cc, ls-hdf5.h, mxarray.h, oct-errno.h, oct-errno.in.cc, oct-fstrm.cc, oct-fstrm.h, oct-handle.h, oct-hist.cc, oct-hist.h, oct-iostrm.cc, oct-iostrm.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.cc, oct-prcstrm.h, oct-procbuf.cc, oct-procbuf.h, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h, oct-tex-lexer.in.ll, pager.cc, pager.h, pr-flt-fmt.cc, pr-flt-fmt.h, pr-output.cc, pr-output.h, procstream.cc, procstream.h, settings.cc, settings.h, sighandlers.cc, sighandlers.h, stack-frame.cc, stack-frame.h, svd.cc, syminfo.cc, syminfo.h, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, toplev.cc, url-handle-manager.cc, url-handle-manager.h, variables.cc, xpow.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, audiodevinfo.cc, gzip.cc, liboctinterp-build-info.h, liboctinterp-build-info.in.cc, mk-build-env-features.sh, mk-builtins.pl, cdef-class.cc, cdef-class.h, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-diag.h, ov-base-int.cc, ov-base-int.h, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base-scalar.h, ov-base-sparse.cc, ov-base-sparse.h, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool-sparse.h, ov-bool.cc, ov-bool.h, ov-builtin.cc, ov-builtin.h, ov-cell.cc, ov-cell.h, ov-ch-mat.cc, ov-ch-mat.h, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-colon.h, ov-complex.cc, ov-complex.h, ov-cs-list.h, ov-cx-diag.cc, ov-cx-diag.h, ov-cx-mat.cc, ov-cx-mat.h, ov-cx-sparse.cc, ov-cx-sparse.h, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.cc, ov-fcn.h, ov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h, ov-flt-cx-diag.cc, ov-flt-cx-diag.h, ov-flt-cx-mat.cc, ov-flt-cx-mat.h, ov-flt-re-diag.cc, ov-flt-re-diag.h, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-java.h, ov-lazy-idx.cc, ov-lazy-idx.h, ov-legacy-range.cc, ov-legacy-range.h, ov-magic-int.cc, ov-magic-int.h, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-null-mat.h, ov-oncleanup.cc, ov-oncleanup.h, ov-perm.cc, ov-perm.h, ov-range.cc, ov-range.h, ov-re-diag.cc, ov-re-diag.h, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h, ov-scalar.cc, ov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov-struct.cc, ov-struct.h, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.cc, ovl.h, octave.cc, octave.h, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, lex.ll, oct-lvalue.cc, oct-lvalue.h, oct-parse.yy, parse.h, profiler.cc, profiler.h, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.h, pt-cbinop.h, pt-cell.h, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.h, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.h, pt.cc, pt.h, token.cc, token.h, usage.h, Array-base.cc, Array.h, CColVector.cc, CColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc, CMatrix.h, CNDArray.cc, CNDArray.h, CRowVector.cc, CRowVector.h, CSparse.cc, CSparse.h, DiagArray2.cc, DiagArray2.h, MArray.cc, MArray.h, MDiagArray2.h, MSparse.h, MatrixType.cc, MatrixType.h, PermMatrix.cc, PermMatrix.h, Range.cc, Range.h, Sparse-b.cc, Sparse.cc, Sparse.h, boolMatrix.cc, boolMatrix.h, boolNDArray.cc, boolNDArray.h, boolSparse.cc, boolSparse.h, chMatrix.h, chNDArray.h, dColVector.cc, dColVector.h, dDiagMatrix.cc, dDiagMatrix.h, dMatrix.cc, dMatrix.h, dNDArray.cc, dNDArray.h, dRowVector.cc, dRowVector.h, dSparse.cc, dSparse.h, dim-vector.cc, dim-vector.h, fCColVector.cc, fCColVector.h, fCDiagMatrix.cc, fCDiagMatrix.h, fCMatrix.cc, fCMatrix.h, fCNDArray.cc, fCNDArray.h, fCRowVector.cc, fCRowVector.h, fColVector.cc, fColVector.h, fDiagMatrix.cc, fDiagMatrix.h, fMatrix.cc, fMatrix.h, fNDArray.cc, fNDArray.h, fRowVector.cc, fRowVector.h, idx-vector.cc, idx-vector.h, intNDArray.cc, intNDArray.h, liboctave-build-info.h, liboctave-build-info.in.cc, CollocWt.cc, CollocWt.h, DAE.h, DAEFunc.h, DAERT.h, DAERTFunc.h, DASPK.cc, DASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h, DET.h, EIG.h, LSODE.cc, LSODE.h, ODE.h, ODEFunc.h, ODES.h, ODESFunc.h, Quad.h, aepbalance.cc, aepbalance.h, base-dae.h, base-de.h, chol.cc, chol.h, eigs-base.cc, fEIG.h, gepbalance.h, gsvd.cc, gsvd.h, hess.h, lu.cc, lu.h, oct-fftw.cc, oct-fftw.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randmtzig.cc, randmtzig.h, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.h, base-list.h, caseless-str.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, data-conv.cc, file-info.h, glob-match.cc, glob-match.h, kpse.cc, kpse.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.cc, lo-ieee.h, lo-regexp.cc, lo-regexp.h, oct-inttypes.cc, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sort.cc, oct-sort.h, oct-sparse.cc, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, singleton-cleanup.cc, singleton-cleanup.h, str-vec.cc, str-vec.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h, version.cc, version.in.h, cxx-signal-helpers.cc, acinclude.m4, main-cli.cc, main-gui.cc, main.in.cc, mkoctfile.in.cc, octave-build-info.h, octave-build-info.in.cc, octave-config.in.cc, octave-svgconvert.cc, shared-fcns.h: maint: Eliminate "(void)" in C++ function prototypes/declarations.
author Rik <rik@octave.org>
date Tue, 24 Jan 2023 17:19:44 -0800
parents 5f11de0e7440
children d607947a6f2a
line wrap: on
line source

// %NO_EDIT_WARNING%

////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2023 The Octave Project Developers
//
// See the file COPYRIGHT.md in the top-level directory of this
// distribution or <https://octave.org/copyright/>.
//
// This file is part of Octave.
//
// Octave 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.
//
// Octave 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 Octave; see the file COPYING.  If not, see
// <https://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////

#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

#include <string>
#include <cstring>
#include <map>
#include <list>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdlib>

#if defined (OCTAVE_USE_WINDOWS_API)
#  include <locale>
#  include <codecvt>
#endif

// Programming note:  The CROSS macro here refers to building a
// cross-compiler aware version of mkoctfile that can be used to cross
// compile .oct file for Windows builds of Octave, not that mkoctfile
// itself is being cross compiled.
//
// We don't use the wrapper and gnulib functions when we are building
// with CROSS defined.  This configuration is only expected to work on
// modern systems that should not need to have gnulib to fix POSIX
// portability problems.  So we just assume a working POSIX system when
// CROSS is defined.

#if defined (CROSS)
#  include <stdlib.h>
#  include <sys/types.h>
#  include <sys/wait.h>
#  include <unistd.h>
#  ifndef OCTAVE_UNUSED
#    define OCTAVE_UNUSED
#  endif
#else
// We are linking against static libs so do not decorate with dllimport.
// FIXME: This should be done by the build system.
#  undef OCTAVE_API
#  define OCTAVE_API
#  include "mkostemps-wrapper.h"
#  include "uniconv-wrappers.h"
#  include "unistd-wrappers.h"
#  include "wait-wrappers.h"
#endif

#if ! defined (OCTAVE_VERSION)
#  define OCTAVE_VERSION %OCTAVE_CONF_VERSION%
#endif

#if ! defined (OCTAVE_PREFIX)
#  define OCTAVE_PREFIX %OCTAVE_CONF_PREFIX%
#endif

#if ! defined (OCTAVE_EXEC_PREFIX)
#  define OCTAVE_EXEC_PREFIX %OCTAVE_CONF_EXEC_PREFIX%
#endif

#include "shared-fcns.h"

#if defined (CROSS)

static int
octave_mkostemps_wrapper (char *tmpl, int suffixlen)
{
  return mkostemps (tmpl, suffixlen, 0);
}

static int
octave_unlink_wrapper (const char *nm)
{
  return unlink (nm);
}

static bool
octave_wifexited_wrapper (int status)
{
  return WIFEXITED (status);
}

static int
octave_wexitstatus_wrapper (int status)
{
  return WEXITSTATUS (status);
}

#endif

static std::string
get_line (FILE *fp)
{
  std::ostringstream buf;

  while (true)
    {
      int c = std::fgetc (fp);

      if (c == '\n' || c == EOF)
        break;

      buf << static_cast<char> (c);
    }

  return buf.str ();
}

static std::string
get_variable (const char *name, const std::string& defval)
{
  const char *val = getenv (name);

  if (val && *val)
    return std::string (val);
  else
    return defval;
}

static std::string
quote_path (const std::string& s)
{
  if (s.find (' ') != std::string::npos && s[0] != '"')
    return '"' + s + '"';
  else
    return s;
}

static std::string
replace_prefix (std::string s)
{
#if defined (OCTAVE_REPLACE_PREFIX)
  const std::string match = "${prefix}";
  const std::string repl = Voctave_exec_home;
  std::size_t pos = s.find (match);
  while (pos != std::string::npos )
    {
      s.replace (pos, match.length (), repl);
      pos = s.find (match);
    }
#endif

  return s;
}

static std::map<std::string, std::string>
make_vars_map (bool link_stand_alone, bool verbose, bool debug)
{
  set_octave_home ();

  std::map<std::string, std::string> vars;

  vars["OCTAVE_HOME"] = Voctave_home;
  vars["OCTAVE_EXEC_HOME"] = Voctave_exec_home;

  vars["API_VERSION"] = %OCTAVE_API_VERSION%;
  vars["CANONICAL_HOST_TYPE"] = %OCTAVE_CANONICAL_HOST_TYPE%;
  vars["DEFAULT_PAGER"] = %OCTAVE_DEFAULT_PAGER%;
  vars["EXEEXT"] = %OCTAVE_EXEEXT%;
  vars["MAN1EXT"] = %OCTAVE_MAN1EXT%;
  vars["OCTAVE_VERSION"] = %OCTAVE_VERSION%;

  vars["ARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_ARCHLIBDIR%);
  vars["BINDIR"] = prepend_octave_exec_home (%OCTAVE_BINDIR%);
  vars["DATADIR"] = prepend_octave_home (%OCTAVE_DATADIR%);
  vars["DATAROOTDIR"] = prepend_octave_home (%OCTAVE_DATAROOTDIR%);
  vars["FCNFILEDIR"] = prepend_octave_home (%OCTAVE_FCNFILEDIR%);
  vars["IMAGEDIR"] = prepend_octave_home (%OCTAVE_IMAGEDIR%);
  vars["INFODIR"] = prepend_octave_home (%OCTAVE_INFODIR%);
  vars["INFOFILE"] = prepend_octave_home (%OCTAVE_INFOFILE%);
  vars["LIBEXECDIR"] = prepend_octave_exec_home (%OCTAVE_LIBEXECDIR%);
  vars["LOCALAPIARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIARCHLIBDIR%);
  vars["LOCALAPIFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALAPIFCNFILEDIR%);
  vars["LOCALAPIOCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALAPIOCTFILEDIR%);
  vars["LOCALARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALARCHLIBDIR%);
  vars["LOCALFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALFCNFILEDIR%);
  vars["LOCALOCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALOCTFILEDIR%);
  vars["LOCALSTARTUPFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALSTARTUPFILEDIR%);
  vars["LOCALVERARCHLIBDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALVERARCHLIBDIR%);
  vars["LOCALVERFCNFILEDIR"] = prepend_octave_home (%OCTAVE_LOCALVERFCNFILEDIR%);
  vars["LOCALVEROCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_LOCALVEROCTFILEDIR%);
  vars["MAN1DIR"] = prepend_octave_home (%OCTAVE_MAN1DIR%);
  vars["MANDIR"] = prepend_octave_home (%OCTAVE_MANDIR%);
  vars["OCTDATADIR"] = prepend_octave_home (%OCTAVE_OCTDATADIR%);
  vars["OCTDOCDIR"] = prepend_octave_home (%OCTAVE_OCTDOCDIR%);
  vars["OCTFILEDIR"] = prepend_octave_exec_home (%OCTAVE_OCTFILEDIR%);
  vars["OCTFONTSDIR"] = prepend_octave_home (%OCTAVE_OCTFONTSDIR%);
  vars["STARTUPFILEDIR"] = prepend_octave_home (%OCTAVE_STARTUPFILEDIR%);

  vars["OCTINCLUDEDIR"]
    = get_variable ("OCTINCLUDEDIR",
                    prepend_octave_home (%OCTAVE_CONF_OCTINCLUDEDIR%));

  vars["INCLUDEDIR"]
    = get_variable ("INCLUDEDIR",
                    prepend_octave_home (%OCTAVE_CONF_INCLUDEDIR%));

  vars["LIBDIR"]
    = get_variable ("LIBDIR", prepend_octave_exec_home (%OCTAVE_CONF_LIBDIR%));

  vars["OCTLIBDIR"]
    = get_variable ("OCTLIBDIR",
                    prepend_octave_exec_home (%OCTAVE_CONF_OCTLIBDIR%));

  std::string DEFAULT_INCFLAGS;

#if defined (OCTAVE_USE_WINDOWS_API)
  DEFAULT_INCFLAGS = "-I" + quote_path (vars["OCTINCLUDEDIR"] + R"(\..)")
                     + " -I" + quote_path (vars["OCTINCLUDEDIR"]);
#else
  DEFAULT_INCFLAGS = "-I" + quote_path (vars["OCTINCLUDEDIR"] + "/..")
                     + " -I" + quote_path (vars["OCTINCLUDEDIR"]);
#endif

  if (vars["INCLUDEDIR"] != "/usr/include")
    DEFAULT_INCFLAGS += " -I" + quote_path (vars["INCLUDEDIR"]);

  std::string DEFAULT_LDFLAGS;

#if (defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS) || defined (OCTAVE_LINK_ALL_DEPS))
  // We'll be linking the files we compile with -loctinterp and -loctave,
  // so we need to know where to find them.
  DEFAULT_LDFLAGS += "-L" + quote_path (vars["OCTLIBDIR"]);
#endif

  if (vars["LIBDIR"] != "/usr/lib")
    DEFAULT_LDFLAGS += " -L" + quote_path (vars["LIBDIR"]);

  vars["CPPFLAGS"] = get_variable ("CPPFLAGS",
                                   replace_prefix (%OCTAVE_CONF_CPPFLAGS%));

  vars["INCFLAGS"] = get_variable ("INCFLAGS", DEFAULT_INCFLAGS);

  vars["F77"] = get_variable ("F77", %OCTAVE_CONF_MKOCTFILE_F77%);

  vars["FFLAGS"] = get_variable ("FFLAGS", %OCTAVE_CONF_FFLAGS%);

  vars["FPICFLAG"] = get_variable ("FPICFLAG", %OCTAVE_CONF_FPICFLAG%);

  vars["CC"] = get_variable ("CC", %OCTAVE_CONF_MKOCTFILE_CC%);
  if (verbose && vars["CC"] == "cc-msvc")
    vars["CC"] += " -d";

  vars["CFLAGS"] = get_variable ("CFLAGS", %OCTAVE_CONF_CFLAGS%);

  vars["CPICFLAG"] = get_variable ("CPICFLAG", %OCTAVE_CONF_CPICFLAG%);

  vars["CXX"] = get_variable ("CXX", %OCTAVE_CONF_MKOCTFILE_CXX%);
  if (verbose && vars["CXX"] == "cc-msvc")
    vars["CXX"] += " -d";

  vars["CXXFLAGS"] = get_variable ("CXXFLAGS", %OCTAVE_CONF_CXXFLAGS%);

  vars["CXXLD"] = get_variable ("CXXLD", vars["CXX"]);
  if (verbose && vars["CXXLD"] == "cc-msvc")
    vars["CXXLD"] += " -d";

  vars["CXXPICFLAG"] = get_variable ("CXXPICFLAG", %OCTAVE_CONF_CXXPICFLAG%);

  vars["XTRA_CFLAGS"] = get_variable ("XTRA_CFLAGS", %OCTAVE_CONF_XTRA_CFLAGS%);

  vars["XTRA_CXXFLAGS"] = get_variable ("XTRA_CXXFLAGS",
                                        %OCTAVE_CONF_XTRA_CXXFLAGS%);

  vars["AR"] = get_variable ("AR", %OCTAVE_CONF_MKOCTFILE_AR%);

  vars["RANLIB"] = get_variable ("RANLIB", %OCTAVE_CONF_MKOCTFILE_RANLIB%);

  vars["DEPEND_FLAGS"] = get_variable ("DEPEND_FLAGS",
                                       %OCTAVE_CONF_DEPEND_FLAGS%);

  vars["DEPEND_EXTRA_SED_PATTERN"]
    = get_variable ("DEPEND_EXTRA_SED_PATTERN",
                    %OCTAVE_CONF_DEPEND_EXTRA_SED_PATTERN%);

  vars["DL_LDFLAGS"] = get_variable ("DL_LDFLAGS",
                                     %OCTAVE_CONF_MKOCTFILE_DL_LDFLAGS%);

  if (! link_stand_alone)
    DEFAULT_LDFLAGS += ' ' + vars["DL_LDFLAGS"];

  vars["RDYNAMIC_FLAG"] = get_variable ("RDYNAMIC_FLAG",
                                        %OCTAVE_CONF_RDYNAMIC_FLAG%);

  vars["LIBOCTAVE"] = "-loctave";

  vars["LIBOCTINTERP"] = "-loctinterp";

  vars["READLINE_LIBS"] = %OCTAVE_CONF_READLINE_LIBS%;

  vars["LAPACK_LIBS"] = get_variable ("LAPACK_LIBS", %OCTAVE_CONF_LAPACK_LIBS%);

  vars["BLAS_LIBS"] = get_variable ("BLAS_LIBS", %OCTAVE_CONF_BLAS_LIBS%);

  vars["FFTW3_LDFLAGS"]
    = get_variable ("FFTW3_LDFLAGS",
                    replace_prefix (%OCTAVE_CONF_FFTW3_LDFLAGS%));

  vars["FFTW3_LIBS"] = get_variable ("FFTW3_LIBS", %OCTAVE_CONF_FFTW3_LIBS%);

  vars["FFTW3F_LDFLAGS"]
    = get_variable ("FFTW3F_LDFLAGS",
                    replace_prefix (%OCTAVE_CONF_FFTW3F_LDFLAGS%));

  vars["FFTW3F_LIBS"] = get_variable ("FFTW3F_LIBS", %OCTAVE_CONF_FFTW3F_LIBS%);

  vars["LIBS"] = get_variable ("LIBS", %OCTAVE_CONF_LIBS%);

  vars["FLIBS"] = get_variable ("FLIBS",
                                replace_prefix (%OCTAVE_CONF_FLIBS%));

  vars["OCTAVE_LINK_DEPS"] = get_variable ("OCTAVE_LINK_DEPS",
                                           %OCTAVE_CONF_MKOCTFILE_OCTAVE_LINK_DEPS%);

  vars["OCTAVE_LINK_OPTS"] = get_variable ("OCTAVE_LINK_OPTS",
                                           %OCTAVE_CONF_OCTAVE_LINK_OPTS%);

  vars["OCT_LINK_DEPS"] = get_variable ("OCT_LINK_DEPS",
                                        %OCTAVE_CONF_MKOCTFILE_OCT_LINK_DEPS%);

  vars["OCT_LINK_OPTS"]
    = get_variable ("OCT_LINK_OPTS",
                    replace_prefix (%OCTAVE_CONF_OCT_LINK_OPTS%));

  vars["LDFLAGS"] = get_variable ("LDFLAGS", DEFAULT_LDFLAGS);

  vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG",
                                         %OCTAVE_CONF_LD_STATIC_FLAG%);

  vars["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG",
                                            %OCTAVE_CONF_F77_INTEGER_8_FLAG%);
  vars["ALL_FFLAGS"] = vars["FFLAGS"] + ' ' + vars["F77_INTEGER8_FLAG"];
  if (debug)
    vars["ALL_FFLAGS"] += " -g";

  vars["ALL_CFLAGS"]
    = vars["INCFLAGS"] + ' ' + vars["XTRA_CFLAGS"] + ' ' + vars["CFLAGS"];
  if (debug)
    vars["ALL_CFLAGS"] += " -g";

  vars["ALL_CXXFLAGS"]
    = vars["INCFLAGS"] + ' ' + vars["XTRA_CXXFLAGS"] + ' ' + vars["CXXFLAGS"];
  if (debug)
    vars["ALL_CXXFLAGS"] += " -g";

  vars["ALL_LDFLAGS"]
    = vars["LD_STATIC_FLAG"] + ' ' + vars["CPICFLAG"] + ' ' + vars["LDFLAGS"];

  vars["OCTAVE_LIBS"]
    = (vars["LIBOCTINTERP"] + ' ' + vars["LIBOCTAVE"] + ' '
       + vars["SPECIAL_MATH_LIB"]);

  vars["FFTW_LIBS"] = vars["FFTW3_LDFLAGS"] + ' ' + vars["FFTW3_LIBS"] + ' '
                      + vars["FFTW3F_LDFLAGS"] + ' ' + vars["FFTW3F_LIBS"];

  return vars;
}

static std::string usage_msg = "usage: mkoctfile [options] file ...";

static std::string version_msg = "mkoctfile, version " OCTAVE_VERSION;

static std::string help_msg =
  "\n"
  "Options:\n"
  "\n"
  "  -h, -?, --help          Print this message.\n"
  "\n"
  "  -IDIR                   Add -IDIR to compile commands.\n"
  "\n"
  "  -idirafter DIR          Add -idirafter DIR to compile commands.\n"
  "\n"
  "  -DDEF                   Add -DDEF to compile commands.\n"
  "\n"
  "  -lLIB                   Add library LIB to link command.\n"
  "\n"
  "  -LDIR                   Add -LDIR to link command.\n"
  "\n"
  "  -M, --depend            Generate dependency files (.d) for C and C++\n"
  "                          source files.\n"
#if ! defined (OCTAVE_USE_WINDOWS_API)
  "\n"
  "  -pthread                Add -pthread to link command.\n"
#endif
  "\n"
  "  -RDIR                   Add -RDIR to link command.\n"
  "\n"
  "  -Wl,...                 Pass flags though the linker like -Wl,-rpath=...\n"
  "\n"
  "  -W...                   Pass flags though the compiler like -Wa,OPTION.\n"
  "\n"
  "  -c, --compile           Compile, but do not link.\n"
  "\n"
  "  -o FILE, --output FILE  Output filename.  Default extension is .oct\n"
  "                          (or .mex if --mex is specified) unless linking\n"
  "                          a stand-alone executable.\n"
  "\n"
  "  -g                      Enable debugging options for compilers.\n"
  "\n"
  "  -p VAR, --print VAR     Print configuration variable VAR.  There are\n"
  "                          three categories of variables:\n"
  "\n"
  "                          Octave configuration variables that users may\n"
  "                          override with environment variables.  These are\n"
  "                          used in commands that mkoctfile executes.\n"
  "\n"
  "                            ALL_CFLAGS                  INCLUDEDIR\n"
  "                            ALL_CXXFLAGS                LAPACK_LIBS\n"
  "                            ALL_FFLAGS                  LDFLAGS\n"
  "                            ALL_LDFLAGS                 LD_STATIC_FLAG\n"
  "                            BLAS_LIBS                   LIBDIR\n"
  "                            CC                          LIBOCTAVE\n"
  "                            CFLAGS                      LIBOCTINTERP\n"
  "                            CPICFLAG                    OCTAVE_LINK_OPTS\n"
  "                            CPPFLAGS                    OCTINCLUDEDIR\n"
  "                            CXX                         OCTAVE_LIBS\n"
  "                            CXXFLAGS                    OCTAVE_LINK_DEPS\n"
  "                            CXXLD                       OCTLIBDIR\n"
  "                            CXXPICFLAG                  OCT_LINK_DEPS\n"
  "                            DL_LDFLAGS                  OCT_LINK_OPTS\n"
  "                            F77                         RDYNAMIC_FLAG\n"
  "                            F77_INTEGER8_FLAG           SPECIAL_MATH_LIB\n"
  "                            FFLAGS                      XTRA_CFLAGS\n"
  "                            FPICFLAG                    XTRA_CXXFLAGS\n"
  "                            INCFLAGS\n"
  "\n"
  "                          Octave configuration variables as above, but\n"
  "                          currently unused by mkoctfile.\n"
  "\n"
  "                            AR\n"
  "                            DEPEND_EXTRA_SED_PATTERN\n"
  "                            DEPEND_FLAGS\n"
  "                            FFTW3F_LDFLAGS\n"
  "                            FFTW3F_LIBS\n"
  "                            FFTW3_LDFLAGS\n"
  "                            FFTW3_LIBS\n"
  "                            FFTW_LIBS\n"
  "                            FLIBS\n"
  "                            LIBS\n"
  "                            RANLIB\n"
  "                            READLINE_LIBS\n"
  "\n"
  "                          Octave configuration variables that are provided\n"
  "                          for informational purposes only.  Except for\n"
  "                          OCTAVE_HOME and OCTAVE_EXEC_HOME, users may not\n"
  "                          override these variables.\n"
  "\n"
  "                          If OCTAVE_HOME or OCTAVE_EXEC_HOME are set in\n"
  "                          the environment, then other variables are adjusted\n"
  "                          accordingly with OCTAVE_HOME or OCTAVE_EXEC_HOME\n"
  "                          substituted for the original value of the directory\n"
  "                          specified by the --prefix or --exec-prefix options\n"
  "                          that were used when Octave was configured.\n"
  "\n"
  "                            API_VERSION                 LOCALFCNFILEDIR\n"
  "                            ARCHLIBDIR                  LOCALOCTFILEDIR\n"
  "                            BINDIR                      LOCALSTARTUPFILEDIR\n"
  "                            CANONICAL_HOST_TYPE         LOCALVERARCHLIBDIR\n"
  "                            DATADIR                     LOCALVERFCNFILEDIR\n"
  "                            DATAROOTDIR                 LOCALVEROCTFILEDIR\n"
  "                            DEFAULT_PAGER               MAN1DIR\n"
  "                            EXEC_PREFIX                 MAN1EXT\n"
  "                            EXEEXT                      MANDIR\n"
  "                            FCNFILEDIR                  OCTAVE_EXEC_HOME\n"
  "                            IMAGEDIR                    OCTAVE_HOME\n"
  "                            INFODIR                     OCTAVE_VERSION\n"
  "                            INFOFILE                    OCTDATADIR\n"
  "                            LIBEXECDIR                  OCTDOCDIR\n"
  "                            LOCALAPIARCHLIBDIR          OCTFILEDIR\n"
  "                            LOCALAPIFCNFILEDIR          OCTFONTSDIR\n"
  "                            LOCALAPIOCTFILEDIR          STARTUPFILEDIR\n"
  "                            LOCALARCHLIBDIR\n"
  "\n"
  "  --link-stand-alone      Link a stand-alone executable file.\n"
  "\n"
  "  --mex                   Assume we are creating a MEX file.  Set the\n"
  "                          default output extension to \".mex\".\n"
  "\n"
  "  -s, --strip             Strip output file.\n"
  "\n"
  "  -n, --just-print, --dry-run\n"
  "                          Print commands, but do not execute them.\n"
  "\n"
  "  -v, --verbose           Echo commands as they are executed.\n"
  "\n"
  "  --silent                Ignored.  Intended to suppress output from\n"
  "                          compiler steps.\n"
  "\n"
  "  FILE                    Compile or link FILE.  Recognized file types are:\n"
  "\n"
  "                            .c    C source\n"
  "                            .cc   C++ source\n"
  "                            .cp   C++ source\n"
  "                            .cpp  C++ source\n"
  "                            .CPP  C++ source\n"
  "                            .cxx  C++ source\n"
  "                            .c++  C++ source\n"
  "                            .C    C++ source\n"
  "                            .f    Fortran source (fixed form)\n"
  "                            .F    Fortran source (fixed form)\n"
  "                            .f90  Fortran source (free form)\n"
  "                            .F90  Fortran source (free form)\n"
  "                            .o    object file\n"
  "                            .a    library file\n"
#if defined (_MSC_VER)
  "                            .lib  library file\n"
#endif
  "\n";

static std::string
basename (const std::string& s, bool strip_path = false)
{
  std::string retval;

  std::size_t pos = s.rfind ('.');

  if (pos == std::string::npos)
    retval = s;
  else
    retval = s.substr (0, pos);

  if (strip_path)
    {
      std::size_t p1 = retval.rfind ('/'), p2 = retval.rfind ('\\');

      pos = (p1 != std::string::npos && p2 != std::string::npos
             ? std::max (p1, p2) : (p2 != std::string::npos ? p2 : p1));

      if (pos != std::string::npos)
        retval = retval.substr (++pos, std::string::npos);
    }

  return retval;
}

inline bool
starts_with (const std::string& s, const std::string& prefix)
{
  return (s.length () >= prefix.length () && s.find (prefix) == 0);
}

inline bool
ends_with (const std::string& s, const std::string& suffix)
{
  return (s.length () >= suffix.length ()
          && s.rfind (suffix) == s.length () - suffix.length ());
}

static int
run_command (const std::string& cmd, bool verbose, bool printonly = false)
{
  if (printonly)
    {
      std::cout << cmd << std::endl;
      return 0;
    }

  if (verbose)
    std::cout << cmd << std::endl;

  // FIXME: Call _wsystem on Windows or octave::sys::system.
  int result = system (cmd.c_str ());

  if (octave_wifexited_wrapper (result))
    result = octave_wexitstatus_wrapper (result);

  return result;
}

bool
is_true (const std::string& s)
{
  return (s == "yes" || s == "true");
}

static std::string
get_temp_directory ()
{
  std::string tempd;

  tempd = octave_getenv ("TMPDIR");

#if defined (__MINGW32__) || defined (_MSC_VER)

  if (tempd.empty ())
    tempd = octave_getenv ("TEMP");

  if (tempd.empty ())
    tempd = octave_getenv ("TMP");

#if defined (P_tmpdir)
  if (tempd.empty ())
    tempd = P_tmpdir;
#endif

  // Some versions of MinGW and MSVC either don't define P_tmpdir, or
  // define it to a single backslash.  In such cases just use C:\temp.
  if (tempd.empty () || tempd == R"(\)")
    tempd = R"(c:\temp)";

#else

#if defined (P_tmpdir)
  if (tempd.empty ())
    tempd = P_tmpdir;
#else
  if (tempd.empty ())
    tempd = "/tmp";
#endif

#endif

  return tempd;
}

static std::string
create_interleaved_complex_file ()
{
  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.c";

  char *ctmpl = new char [tmpl.length () + 1];

  ctmpl = strcpy (ctmpl, tmpl.c_str ());

  // mkostemps will open the file and return a file descriptor.  We
  // won't worry about closing it because we will need the file until we
  // are done and then the file will be closed when mkoctfile exits.
  int fd = octave_mkostemps_wrapper (ctmpl, 2);

  // Make C++ string from filled-in template.
  std::string retval (ctmpl);
  delete [] ctmpl;

  // Write symbol definition to file.
  FILE *fid = fdopen (fd, "w");
  fputs ("const int __mx_has_interleaved_complex__ = 1;\n", fid);
  fclose (fid);

  return retval;
}

static std::string
tmp_objfile_name ()
{
  std::string tmpl = get_temp_directory () + "/oct-XXXXXX.o";

  char *ctmpl = new char [tmpl.length () + 1];

  ctmpl = strcpy (ctmpl, tmpl.c_str ());

  // mkostemps will open the file and return a file descriptor.  We
  // won't worry about closing it because we will need the file until we
  // are done and then the file will be closed when mkoctfile exits.
  octave_mkostemps_wrapper (ctmpl, 2);

  std::string retval (ctmpl);  // make C++ string from filled-in template
  delete [] ctmpl;

  return retval;
}

static void
clean_up_tmp_files (const std::list<std::string>& tmp_files)
{
  for (const auto& file : tmp_files)
    octave_unlink_wrapper (file.c_str ());
}

#if defined (OCTAVE_USE_WINDOWS_API) && defined (_UNICODE)
extern "C"
int
wmain (int argc, wchar_t **sys_argv)
{
  std::vector<std::string> argv;

  // Convert wide character strings to multibyte UTF-8 strings and save
  // them in a vector of std::string objects for later processing.

  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
  for (int i_arg = 0; i_arg < argc; i_arg++)
    argv.push_back (wchar_conv.to_bytes (sys_argv[i_arg]));
#else
int
main (int argc, char **sys_argv)
{
  std::vector<std::string> argv;

  // Save args as vector of std::string objects for later processing.
  for (int i_arg = 0; i_arg < argc; i_arg++)
    argv.push_back (sys_argv[i_arg]);
#endif

  if (argc == 1)
    {
      std::cout << usage_msg << std::endl;
      return 1;
    }

  if (argc == 2 && (argv[1] == "-v" || argv[1] == "-version"
                    || argv[1] == "--version"))
    {
      std::cout << version_msg << std::endl;
      return 0;
    }

  std::list<std::string> cfiles, ccfiles, f77files, tmp_objfiles;
  std::string output_ext = ".oct";
  std::string objfiles, libfiles, octfile, outputfile;
  std::string incflags, defs, ldflags, pass_on_options;
  std::string var_to_print;
  bool debug = false;
  bool verbose = false;
  bool strip = false;
  bool no_oct_file_strip_on_this_platform = is_true ("%NO_OCT_FILE_STRIP%");
  bool compile_only = false;
  bool link_stand_alone = false;
  bool depend = false;
  bool printonly = false;
  bool output_file_option = false;
  bool creating_mex_file = false;
  bool r2017b_option = false;
  bool r2018a_option = false;
  // The default for this may change in the future.
  bool mx_has_interleaved_complex = false;

  for (int i = 1; i < argc; i++)
    {
      std::string arg = argv[i];

      std::string file;

      if (ends_with (arg, ".c"))
        {
          file = arg;
          cfiles.push_back (file);
        }
      else if (ends_with (arg, ".cc") || ends_with (arg, ".cp")
               || ends_with (arg, ".cpp") || ends_with (arg, ".CPP")
               || ends_with (arg, ".cxx") || ends_with (arg, ".c++")
               || ends_with (arg, ".C"))
        {
          file = arg;
          ccfiles.push_back (file);
        }
      else if (ends_with (arg, ".f") || ends_with (arg, ".F")
               || ends_with (arg, "f90") || ends_with (arg, ".F90"))
        {
          file = arg;
          f77files.push_back (file);
        }
      else if (ends_with (arg, ".o") || ends_with (arg, ".obj"))
        {
          file = arg;
          objfiles += (' ' + quote_path (arg));
        }
      else if (ends_with (arg, ".lib") || ends_with (arg, ".a"))
        {
          file = arg;
          libfiles += (' ' + quote_path (arg));
        }
      else if (arg == "-d" || arg == "-debug" || arg == "--debug"
               || arg == "-v" || arg == "-verbose" ||  arg == "--verbose")
        {
          verbose = true;
        }
      else if (arg == "-silent" ||  arg == "--silent")
        {
          // Ignored for now.
        }
      else if (arg == "-h" || arg == "-?" || arg == "-help" || arg == "--help")
        {
          std::cout << usage_msg << std::endl;
          std::cout << help_msg << std::endl;
          return 0;
        }
      else if (starts_with (arg, "-I"))
        {
          incflags += (' ' + quote_path (arg));
        }
      else if (arg == "-idirafter")
        {
          if (i < argc-1)
            {
              arg = argv[++i];
              incflags += (" -idirafter " + arg);
            }
          else
            std::cerr << "mkoctfile: include directory name missing"
                      << std::endl;
        }
      else if (starts_with (arg, "-D"))
        {
          defs += (' ' + arg);
        }
      else if (arg == "-largeArrayDims" || arg == "-compatibleArrayDims")
        {
          std::cerr << "mkoctfile: warning: -largeArrayDims and -compatibleArrayDims are accepted for compatibility, but ignored" << std::endl;
        }
      else if (arg == "-R2017b")
        {
          if (r2018a_option)
            {
              std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
              return 1;
            }

          r2017b_option = true;
        }
      else if (arg == "-R2018a")
        {
          if (r2017b_option)
            {
              std::cerr << "mkoctfile: only one of -R2017b and -R2018a may be used" << std::endl;
              return 1;
            }

          r2018a_option = true;
          mx_has_interleaved_complex = true;
        }
      else if (starts_with (arg, "-Wl,") || starts_with (arg, "-l")
               || starts_with (arg, "-L") || starts_with (arg, "-R"))
        {
          ldflags += (' ' + quote_path (arg));
        }
#if ! defined (OCTAVE_USE_WINDOWS_API)
      else if (arg == "-pthread")
        {
          ldflags += (' ' + arg);
        }
#endif
      else if (arg == "-M" || arg == "-depend" || arg == "--depend")
        {
          depend = true;
        }
      else if (arg == "-o" || arg == "-output" || arg == "--output")
        {
          output_file_option = true;

          if (i < argc-1)
            {
              arg = argv[++i];
              outputfile = arg;
            }
          else
            std::cerr << "mkoctfile: output filename missing" << std::endl;
        }
      else if (arg == "-n" || arg == "--dry-run" || arg == "--just-print")
        {
          printonly = true;
        }
      else if (arg == "-p" || arg == "-print" || arg == "--print")
        {
          if (i < argc-1)
            {
              ++i;

              if (! var_to_print.empty ())
                std::cerr << "mkoctfile: warning: only one '" << arg
                          << "' option will be processed" << std::endl;
              else
                var_to_print = argv[i];
            }
          else
            std::cerr << "mkoctfile: --print requires argument" << std::endl;
        }
      else if (arg == "-s" || arg == "-strip" || arg == "--strip")
        {
          if (no_oct_file_strip_on_this_platform)
            std::cerr << "mkoctfile: stripping disabled on this platform"
                      << std::endl;
          else
            strip = true;
        }
      else if (arg == "-c" || arg == "-compile" || arg == "--compile")
        {
          compile_only = true;
        }
      else if (arg == "-g")
        {
          debug = true;
        }
      else if (arg == "-link-stand-alone" || arg == "--link-stand-alone")
        {
          link_stand_alone = true;
        }
      else if (arg == "-mex" || arg == "--mex")
        {
          creating_mex_file = true;

          incflags += " -I.";
#if defined (_MSC_VER)
          ldflags += " -Wl,-export:mexFunction";
#endif
          output_ext = ".mex";
        }
      else if (starts_with (arg, "-W"))
        {
          pass_on_options += (' ' + arg);
        }
      else if (starts_with (arg, "-O"))
        {
          pass_on_options += (' ' + arg);
        }
      else if (starts_with (arg, "-"))
        {
          // Pass through any unrecognized options.
          pass_on_options += (' ' + arg);
          // Check for an additional argument following the option.
          // However, don't check the final position which is typically a file
          if (i < argc-2)
            {
              arg = argv[i+1];
              if (arg[0] != '-')
                {
                  pass_on_options += (' ' + arg);
                  i++;
                }
            }
        }
      else
        {
          std::cerr << "mkoctfile: unrecognized argument " << arg << std::endl;
          return 1;
        }

      if (! file.empty () && octfile.empty ())
        octfile = file;
    }

  std::map<std::string, std::string> vars
    = make_vars_map (link_stand_alone, verbose, debug);

  if (! var_to_print.empty ())
    {
      if (vars.find (var_to_print) == vars.end ())
        {
          std::cerr << "mkoctfile: unknown variable '" << var_to_print << "'"
                    << std::endl;
          return 1;
        }

      std::cout << vars[var_to_print] << std::endl;

      return 0;
    }

  if (creating_mex_file)
    {
      if (vars["ALL_CFLAGS"].find ("-g") != std::string::npos)
        defs += " -DMEX_DEBUG";

      if (mx_has_interleaved_complex)
        {
          defs += " -DMX_HAS_INTERLEAVED_COMPLEX=1";

          if (! compile_only)
            {
              // Create tmp C source file that defines an extern symbol
              // that can be checked when loading the mex file to
              // determine that the file was compiled expecting
              // interleaved complex values.

              std::string tmp_file = create_interleaved_complex_file ();

              cfiles.push_back (tmp_file);
            }
        }
    }
  else
    {
      if (r2017b_option)
        std::cerr << "mkoctfile: warning: -R2017b option ignored unless creating mex file"
                  << std::endl;

      if (r2018a_option)
        std::cerr << "mkoctfile: warning: -R2018a option ignored unless creating mex file"
                  << std::endl;
    }

  if (compile_only && output_file_option
      && (cfiles.size () + ccfiles.size () + f77files.size ()) > 1)
    {
      std::cerr << "mkoctfile: may not use -c and -o with multiple source files"
                << std::endl;
      return 1;
    }

  std::string output_option;

  if (link_stand_alone)
    {
      if (! outputfile.empty ())
        output_option = "-o " + outputfile;
    }
  else
    {
      if (! outputfile.empty ())
        {
          // FIXME: should probably do a better job of finding the
          // filename extension instead of just looking at the filename
          // length.

          octfile = outputfile;
          std::size_t len = octfile.length ();
          std::size_t len_ext = output_ext.length ();
          if (len <= len_ext || octfile.substr (len-len_ext) != output_ext)
            octfile += output_ext;
        }
      else
        octfile = basename (octfile, true) + output_ext;
    }

  if (depend)
    {
#if defined (OCTAVE_USE_WINDOWS_API) && ! defined (_UNICODE)
      std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_conv;
#endif

      for (const auto& f : cfiles)
        {
          std::string dfile = basename (f, true) + ".d", line;

          octave_unlink_wrapper (dfile.c_str ());

          std::string cmd
            = (vars["CC"] + ' ' + vars["DEPEND_FLAGS"] + ' '
               + vars["CPPFLAGS"] + ' ' + vars["ALL_CFLAGS"] + ' '
               + incflags  + ' ' + defs + ' ' + quote_path (f));

#if defined (OCTAVE_USE_WINDOWS_API)
          FILE *fd;
          try
            {
              std::wstring wcmd = wchar_conv.from_bytes (cmd);
              fd = ::_wpopen (wcmd.c_str (), L"r");
            }
          catch (const std::range_error& e)
            {
              fd = ::popen (cmd.c_str (), "r");
            }

          std::ofstream fo;
          try
            {
              std::wstring wfile = wchar_conv.from_bytes (dfile);
              fo.open (wfile.c_str ());
            }
          catch (const std::range_error& e)
            {
              fo.open (dfile.c_str ());
            }
#else
          FILE *fd = popen (cmd.c_str (), "r");

          std::ofstream fo (dfile.c_str ());
#endif

          std::size_t pos;
          while (! feof (fd))
            {
              line = get_line (fd);
              if ((pos = line.rfind (".o:")) != std::string::npos)
                {
                  std::size_t spos = line.rfind ('/', pos);
                  std::string ofile
                    = (spos == std::string::npos
                       ? line.substr (0, pos+2)
                       : line.substr (spos+1, pos-spos+1));
                  fo << "pic/" << ofile << ' ' << ofile << ' '
                     << dfile << line.substr (pos) << std::endl;
                }
              else
                fo << line << std::endl;
            }
          pclose (fd);
          fo.close ();
        }

      for (const auto& f : ccfiles)
        {
          std::string dfile = basename (f, true) + ".d", line;

          octave_unlink_wrapper (dfile.c_str ());

          std::string cmd
            = (vars["CXX"] + ' ' + vars["DEPEND_FLAGS"] + ' '
               + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
               + incflags  + ' ' + defs + ' ' + quote_path (f));

#if defined (OCTAVE_USE_WINDOWS_API)
          FILE *fd;
          try
            {
              std::wstring wcmd = wchar_conv.from_bytes (cmd);
              fd = ::_wpopen (wcmd.c_str (), L"r");
            }
          catch (const std::range_error& e)
            {
              fd = ::popen (cmd.c_str (), "r");
            }

          std::ofstream fo;
          try
            {
              std::wstring wfile = wchar_conv.from_bytes (dfile);
              fo.open (wfile.c_str ());
            }
          catch (const std::range_error& e)
            {
              fo.open (dfile.c_str ());
            }
#else
          FILE *fd = popen (cmd.c_str (), "r");

          std::ofstream fo (dfile.c_str ());
#endif

          std::size_t pos;
          while (! feof (fd))
            {
              line = get_line (fd);
              if ((pos = line.rfind (".o:")) != std::string::npos)
                {
                  std::size_t spos = line.rfind ('/', pos);
                  std::string ofile
                    = (spos == std::string::npos
                       ? line.substr (0, pos+2)
                       : line.substr (spos+1, pos-spos+1));
                  fo << "pic/" << ofile << ' ' << ofile << ' '
                     << dfile << line.substr (pos+2) << std::endl;
                }
              else
                fo << line << std::endl;
            }
          pclose (fd);
          fo.close ();
        }

      return 0;
    }

  for (const auto& f : f77files)
    {
      if (! vars["F77"].empty ())
        {
          std::string o;
          if (compile_only)
            {
              if (! outputfile.empty ())
                o = outputfile;
              else
                o = basename (f, true) + ".o";
            }
          else
            {
              o = tmp_objfile_name ();

              tmp_objfiles.push_back (o);

              objfiles += (' ' + o);
            }

          std::string cmd
            = (vars["F77"] + " -c " + vars["FPICFLAG"] + ' '
               + vars["ALL_FFLAGS"] + ' ' + incflags + ' ' + defs + ' '
               + pass_on_options + ' ' + quote_path (f)
               + " -o " + quote_path (o));

          int status = run_command (cmd, verbose, printonly);

          if (status)
            return status;
        }
      else
        {
          std::cerr << "mkoctfile: no way to compile Fortran file " << f
                    << std::endl;
          return 1;
        }
    }

  for (const auto& f : cfiles)
    {
      if (! vars["CC"].empty ())
        {
          std::string o;
          if (compile_only)
            {
              if (! outputfile.empty ())
                o = outputfile;
              else
                o = basename (f, true) + ".o";
            }
          else
            {
              o = tmp_objfile_name ();

              tmp_objfiles.push_back (o);

              objfiles += (' ' + o);
            }

          std::string cmd
            = (vars["CC"] + " -c " + vars["CPPFLAGS"] + ' '
               + vars["CPICFLAG"] + ' ' + vars["ALL_CFLAGS"] + ' '
               + pass_on_options + ' ' + incflags + ' ' + defs + ' '
               + quote_path (f) + " -o " + quote_path (o));

          int status = run_command (cmd, verbose, printonly);

          if (status)
            return status;
        }
      else
        {
          std::cerr << "mkoctfile: no way to compile C file " << f
                    << std::endl;
          return 1;
        }
    }

  for (const auto& f : ccfiles)
    {
      if (! vars["CXX"].empty ())
        {
          std::string o;
          if (compile_only)
            {
              if (! outputfile.empty ())
                o = outputfile;
              else
                o = basename (f, true) + ".o";
            }
          else
            {
              o = tmp_objfile_name ();

              tmp_objfiles.push_back (o);

              objfiles += (' ' + o);
            }

          std::string cmd
            = (vars["CXX"] + " -c " + vars["CPPFLAGS"] + ' '
               + vars["CXXPICFLAG"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
               + pass_on_options + ' ' + incflags + ' ' + defs + ' '
               + quote_path (f) + " -o " + quote_path (o));

          int status = run_command (cmd, verbose, printonly);

          if (status)
            return status;
        }
      else
        {
          std::cerr << "mkoctfile: no way to compile C++ file " << f
                    << std::endl;
          return 1;
        }
    }

  // If we are only compiling, we are done.

  if (compile_only)
    return 0;

  if (objfiles.empty ())
    {
      std::cerr << "mkoctfile: no objects to link" << std::endl;
      return 1;
    }

  std::string octave_libs;

  if (link_stand_alone)
    {
      if (! vars["CXXLD"].empty ())
        {
          octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
                        + ' ' + vars["OCTAVE_LIBS"];

          std::string cmd
            = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' '
               + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' '
               + pass_on_options + ' ' + output_option + ' ' + objfiles + ' '
               + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' '
               + octave_libs + ' '
               + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]);

          int status = run_command (cmd, verbose, printonly);

          clean_up_tmp_files (tmp_objfiles);

          if (status)
            return status;
        }
      else
        {
          std::cerr
            << "mkoctfile: no way to link stand-alone executable file"
            << std::endl;
          return 1;
        }
    }
  else
    {
#if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
      octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
                    + ' ' + vars["OCTAVE_LIBS"];
#endif

      std::string cmd
        = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' '
           + pass_on_options + " -o " + octfile + ' ' + objfiles + ' '
           + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' '
           + vars["LDFLAGS"] + ' ' + octave_libs + ' '
           + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);

#if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
      if (! f77files.empty () && ! vars["FLIBS"].empty ())
        cmd += ' ' + vars["FLIBS"];
#endif

      int status = run_command (cmd, verbose, printonly);

      clean_up_tmp_files (tmp_objfiles);

      if (status)
        return status;
    }

  if (strip)
    {
      std::string cmd = "strip " + octfile;

      int status = run_command (cmd, verbose, printonly);

      if (status)
        return status;
    }

  return 0;
}