lyx_mirror/src/support/os.cpp
Jean-Marc Lasgouttes 5e33e4fc2c Catch improbable exception
We know that the exception is correct, but coverity does not.
It would be much better to check that at compile time...
2019-07-13 00:24:21 +02:00

160 lines
4.3 KiB
C++

/**
* \file os.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Ruurd A. Reitsma
* \author Enrico Forestieri
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "support/convert.h"
#include "support/debug.h"
#include "support/filetools.h"
#include "support/qstring_helpers.h"
#include "support/regex.h"
#include <QDir>
#if defined(__CYGWIN__)
#include "support/os_cygwin.cpp"
#elif defined(_WIN32)
#include "support/os_win32.cpp"
#else
#include "support/os_unix.cpp"
#endif
// Static assert to break compilation on platforms where
// int/unsigned int is not 4 bytes. Added to make sure that
// e.g., the author hash is always 32-bit.
template<bool Condition> struct static_assert_helper;
template <> struct static_assert_helper<true> {};
enum {
dummy = sizeof(static_assert_helper<sizeof(int) == 4>)
};
namespace lyx {
namespace support {
namespace os {
int timeout_min()
{
return 3;
}
static string const python23_call(string const & binary, bool verbose = false)
{
const string version_info = " -c 'from __future__ import print_function;import sys; print(sys.version_info[:2], end=\"\")'";
// Default to "python" if no binary is given.
if (binary.empty())
return "python -tt";
if (verbose)
lyxerr << "Examining " << binary << "\n";
// Check whether this is a python 2 or 3 binary.
cmd_ret const out = runCommand(binary + version_info);
smatch sm;
try {
static regex const python_reg("\\((\\d*), (\\d*)\\)");
if (out.first < 0 || !regex_match(out.second, sm, python_reg))
return string();
} catch(regex_error const & /*e*/) {
LYXERR0("Regex error! This should not happen.");
return string();
}
int major = convert<int>(sm.str(1));
int minor = convert<int>(sm.str(2));
if((major == 2 && minor < 7) || (major == 3 && minor < 5))
return string();
if (verbose)
lyxerr << "Found Python " << out.second << "\n";
// Add the -tt switch so that mixed tab/whitespace
// indentation is an error
return binary + " -tt";
}
static string const find_python_binary()
{
// This function takes inspiration from PEP 394 and PEP 397
// PEP 394 -- The "python" Command on Unix-Like Systems
// https://www.python.org/dev/peps/pep-0394/
// PEP 397 -- Python launcher for Windows
// https://www.python.org/dev/peps/pep-0397/
// Check whether python3 in PATH is the right one.
string command = python23_call("python3");
if (!command.empty())
return command;
// python3 does not exists, let us try to find python3.x in PATH
// the search is probably broader than required
// but we are trying hard to find a valid python binary
vector<string> const path = getEnvPath("PATH");
lyxerr << "Looking for python 3.x ...\n";
for (auto bin: path) {
QString const dir = toqstr(bin);
string const localdir = dir.toLocal8Bit().constData();
QDir qdir(dir);
qdir.setFilter(QDir::Files | QDir::Executable);
QStringList list = qdir.entryList(QStringList("python3*"));
for (auto bin: list) {
string const binary = addName(localdir,
bin.toLocal8Bit().constData());
command = python23_call(binary, true);
if (!command.empty())
return command;
}
}
// python 3 was not found let us look for python 2
command = python23_call("python2");
if (!command.empty())
return command;
// python2 does not exists, let us try to find python2.x in PATH
// the search is probably broader than required
// but we are trying hard to find a valid python binary
lyxerr << "Looking for python 2.x ...\n";
for (auto bin: path) {
QString const dir = toqstr(bin);
string const localdir = dir.toLocal8Bit().constData();
QDir qdir(dir);
qdir.setFilter(QDir::Files | QDir::Executable);
QStringList list = qdir.entryList(QStringList("python2*"));
for (auto bin: list) {
string const binary = addName(localdir,
bin.toLocal8Bit().constData());
command = python23_call(binary, true);
if (!command.empty())
return command;
}
}
// If this happens all hope is lost that this is a sane system
lyxerr << "Warning: No python v2.x or 3.x binary found.\n";
return python23_call("");
}
string const python(bool reset)
{
static string command = find_python_binary();
// FIXME THREAD
if (reset) {
command = find_python_binary();
}
return command;
}
} // namespace os
} // namespace support
} // namespace lyx