mirror of
https://git.lyx.org/repos/lyx.git
synced 2025-01-18 21:45:24 +00:00
Backport the 1.4.x code to
* Split a string into an argv array of words to pass to execvp; * handle the $$s placeholder in converter definitions. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_3_X@9569 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
44cbcdb6aa
commit
18d5578a5f
@ -1,3 +1,7 @@
|
||||
2005-01-20 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* configure.m4: Invoke scripts as "python $$s/scripts/foo.py", etc.
|
||||
|
||||
2005-01-02 Kayvan A. Sylvan <kayvan@sylvan.com>
|
||||
|
||||
* configure.m4: add \cygwin_path_fix_needed to lyrxc.defaults.
|
||||
|
@ -297,7 +297,7 @@ SEARCH_PROG([for a DVI to PDF converter],dvi_to_pdf_command,dvipdfm)
|
||||
test $dvi_to_pdf_command = "dvipdfm" && dvi_to_pdf_command="dvipdfm \$\$i"
|
||||
|
||||
# We have a script to convert previewlyx to ppm
|
||||
lyxpreview_to_bitmap_command="lyxpreview2ppm.py"
|
||||
lyxpreview_to_bitmap_command="python \$\$s/scripts/lyxpreview2ppm.py"
|
||||
|
||||
# Search a *roff program (used to translate tables in ASCII export)
|
||||
LYXRC_PROG([for a *roff formatter], \ascii_roff_command, dnl
|
||||
|
@ -1,3 +1,8 @@
|
||||
2005-01-20 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* FormPreferences.C: change the tooltip messages to reflect the
|
||||
changed meaning of the $$s placeholder.
|
||||
|
||||
2005-01-15 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* FormPreferences.C, forms/form_preferences.fd: add an interface
|
||||
|
@ -993,9 +993,9 @@ FormPreferences::Converters::feedback(FL_OBJECT const * const ob) const
|
||||
|
||||
if (ob == dialog_->input_converter)
|
||||
return _("The conversion command. $$i is the input file name, "
|
||||
"$$b is the file name without its extension and $$o is "
|
||||
"the name of the output file. $$s can be used as path to "
|
||||
"LyX's own collection of conversion scripts.");
|
||||
"$$b is the file name without its extension and $$o "
|
||||
"is the name of the output file. $$s can be used "
|
||||
"as the path to LyX's support directory.");
|
||||
|
||||
if (ob == dialog_->input_flags)
|
||||
return _("Extra information for the Converter class, whether and "
|
||||
|
@ -1,3 +1,12 @@
|
||||
2005-01-20 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* filetools.[Ch] (LibScriptSearch): backport the 1.4.x code so
|
||||
that the function now substitutes the $$s placeholder for the
|
||||
path to the appropriate LyX support directory.
|
||||
|
||||
* forkedcall.C (generateChild): backport the 1.4.x code to split
|
||||
the input command up into an array of words and to strip any quotes.
|
||||
|
||||
2005-01-30 Angus Leeming <leeming@lyx.org>
|
||||
|
||||
* os_cygwin.C (cygwin_path_fix):
|
||||
|
@ -349,18 +349,36 @@ i18nLibFileSearch(string const & dir, string const & name,
|
||||
}
|
||||
|
||||
|
||||
string const LibScriptSearch(string const & command)
|
||||
string const LibScriptSearch(string const & command_in)
|
||||
{
|
||||
string script;
|
||||
string args = command;
|
||||
args = split(args, script, ' ');
|
||||
script = LibFileSearch("scripts", script);
|
||||
if (script.empty())
|
||||
string const token_scriptpath("$$s/");
|
||||
|
||||
string command = command_in;
|
||||
// Find the starting position of "$$s/"
|
||||
string::size_type const pos1 = command.find(token_scriptpath);
|
||||
if (pos1 == string::npos)
|
||||
return command;
|
||||
else if (args.empty())
|
||||
return script;
|
||||
else
|
||||
return script + ' ' + args;
|
||||
// Find the end of the "$$s/some_script" word within command.
|
||||
// Assumes that the script name does not contain spaces.
|
||||
string::size_type const start_script = pos1 + 4;
|
||||
string::size_type const pos2 = command.find(' ', start_script);
|
||||
string::size_type const size_script = pos2 == string::npos?
|
||||
(command.size() - start_script) : pos2 - start_script;
|
||||
|
||||
// Does this script file exist?
|
||||
string const script =
|
||||
LibFileSearch(".", command.substr(start_script, size_script));
|
||||
|
||||
if (script.empty()) {
|
||||
// Replace "$$s/" with ""
|
||||
command.erase(pos1, 4);
|
||||
} else {
|
||||
// Replace "$$s/foo/some_script" with "<path to>/some_script".
|
||||
string::size_type const size_replace = size_script + 4;
|
||||
command.replace(pos1, size_replace, QuoteName(script));
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
|
@ -96,11 +96,13 @@ string const
|
||||
i18nLibFileSearch(string const & dir, string const & name,
|
||||
string const & ext = string());
|
||||
|
||||
/** Takes a command with arguments as input and tries to see whether
|
||||
the command itself can be found in one of the scripts/ directories.
|
||||
If it is found, return the command with fully qualified script name,
|
||||
either return it unchanged */
|
||||
string const LibScriptSearch(string const & command);
|
||||
/** Takes a command such as "sh $$s/scripts/convertDefault.sh file.in file.out"
|
||||
* and replaces "$$s/" with the path to the LyX support directory containing
|
||||
* this script. If the script is not found, "$$s/" is removed. Executing the
|
||||
* command will still fail, but the error message will make some sort of
|
||||
* sense ;-)
|
||||
*/
|
||||
std::string const LibScriptSearch(std::string const & command);
|
||||
|
||||
///
|
||||
string const GetEnv(string const & envname);
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <cerrno>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
@ -45,6 +46,7 @@
|
||||
#endif
|
||||
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
|
||||
#ifndef CXX_GLOBAL_CSTD
|
||||
using std::strerror;
|
||||
@ -251,31 +253,70 @@ int Forkedcall::startscript(string const & what, SignalTypePtr signal)
|
||||
// generate child in background
|
||||
int Forkedcall::generateChild()
|
||||
{
|
||||
// Split command_ up into a char * array
|
||||
int const MAX_ARGV = 255;
|
||||
char *argv[MAX_ARGV];
|
||||
string line = trim(command_);
|
||||
if (line.empty())
|
||||
return 1;
|
||||
|
||||
string line = command_;
|
||||
int index = 0;
|
||||
for (; index < MAX_ARGV-1; ++index) {
|
||||
string word;
|
||||
line = split(line, word, ' ');
|
||||
if (word.empty())
|
||||
break;
|
||||
// Split the input command up into an array of words stored
|
||||
// in a contiguous block of memory. The array contains pointers
|
||||
// to each word.
|
||||
// Don't forget the terminating `\0' character.
|
||||
char const * const c_str = line.c_str();
|
||||
vector<char> vec(c_str, c_str + line.size() + 1);
|
||||
|
||||
char * tmp = new char[word.length() + 1];
|
||||
word.copy(tmp, word.length());
|
||||
tmp[word.length()] = '\0';
|
||||
|
||||
argv[index] = tmp;
|
||||
// Splitting the command up into an array of words means replacing
|
||||
// the whitespace between words with '\0'. Life is complicated
|
||||
// however, because words protected by quotes can contain whitespace.
|
||||
//
|
||||
// The strategy we adopt is:
|
||||
// 1. If we're not inside quotes, then replace white space with '\0'.
|
||||
// 2. If we are inside quotes, then don't replace the white space
|
||||
// but do remove the quotes themselves. We do this naively by
|
||||
// replacing the quote with '\0' which is fine if quotes
|
||||
// delimit the entire word.
|
||||
char inside_quote = 0;
|
||||
vector<char>::iterator it = vec.begin();
|
||||
vector<char>::iterator const end = vec.end();
|
||||
for (; it != end; ++it) {
|
||||
char const c = *it;
|
||||
if (!inside_quote) {
|
||||
if (c == ' ')
|
||||
*it = '\0';
|
||||
else if (c == '\'' || c == '"') {
|
||||
*it = '\0';
|
||||
inside_quote = c;
|
||||
}
|
||||
} else if (c == inside_quote) {
|
||||
*it = '\0';
|
||||
inside_quote = 0;
|
||||
}
|
||||
}
|
||||
argv[index] = 0;
|
||||
|
||||
// Build an array of pointers to each word.
|
||||
it = vec.begin();
|
||||
vector<char *> argv;
|
||||
char prev = '\0';
|
||||
for (; it != end; ++it) {
|
||||
if (*it != '\0' && prev == '\0')
|
||||
argv.push_back(&*it);
|
||||
prev = *it;
|
||||
}
|
||||
argv.push_back(0);
|
||||
|
||||
// Debug output.
|
||||
vector<char *>::iterator ait = argv.begin();
|
||||
vector<char *>::iterator const aend = argv.end();
|
||||
lyxerr << "<command>\n";
|
||||
for (; ait != aend; ++ait)
|
||||
if (*ait)
|
||||
lyxerr << '\t'<< *ait << '\n';
|
||||
lyxerr << "</command>" << std::endl;
|
||||
|
||||
#ifndef __EMX__
|
||||
pid_t const cpid = ::fork();
|
||||
if (cpid == 0) {
|
||||
// Child
|
||||
execvp(argv[0], argv);
|
||||
execvp(argv[0], &*argv.begin());
|
||||
|
||||
// If something goes wrong, we end up here
|
||||
lyxerr << "execvp of \"" << command_ << "\" failed: "
|
||||
@ -284,7 +325,7 @@ int Forkedcall::generateChild()
|
||||
}
|
||||
#else
|
||||
pid_t const cpid = spawnvp(P_SESSION|P_DEFAULT|P_MINIMIZE|P_BACKGROUND,
|
||||
argv[0], argv);
|
||||
argv[0], &*argv.begin());
|
||||
#endif
|
||||
|
||||
if (cpid < 0) {
|
||||
@ -292,12 +333,5 @@ int Forkedcall::generateChild()
|
||||
lyxerr << "Could not fork: " << strerror(errno) << endl;
|
||||
}
|
||||
|
||||
// Clean-up.
|
||||
for (int i = 0; i < MAX_ARGV; ++i) {
|
||||
if (argv[i] == 0)
|
||||
break;
|
||||
delete [] argv[i];
|
||||
}
|
||||
|
||||
return cpid;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user