diff --git a/lib/ChangeLog b/lib/ChangeLog index a798c68883..fd3fdacf08 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,7 @@ +2005-01-20 Angus Leeming + + * configure.m4: Invoke scripts as "python $$s/scripts/foo.py", etc. + 2005-01-02 Kayvan A. Sylvan * configure.m4: add \cygwin_path_fix_needed to lyrxc.defaults. diff --git a/lib/configure.m4 b/lib/configure.m4 index 6837c974f3..2bcda1b21f 100644 --- a/lib/configure.m4 +++ b/lib/configure.m4 @@ -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 diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 3d859861b0..2b91f0e5a5 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,8 @@ +2005-01-20 Angus Leeming + + * FormPreferences.C: change the tooltip messages to reflect the + changed meaning of the $$s placeholder. + 2005-01-15 Angus Leeming * FormPreferences.C, forms/form_preferences.fd: add an interface diff --git a/src/frontends/xforms/FormPreferences.C b/src/frontends/xforms/FormPreferences.C index 4747786f7a..74f9dc3c73 100644 --- a/src/frontends/xforms/FormPreferences.C +++ b/src/frontends/xforms/FormPreferences.C @@ -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 " diff --git a/src/support/ChangeLog b/src/support/ChangeLog index 9629df4208..315a310736 100644 --- a/src/support/ChangeLog +++ b/src/support/ChangeLog @@ -1,3 +1,12 @@ +2005-01-20 Angus Leeming + + * 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 * os_cygwin.C (cygwin_path_fix): diff --git a/src/support/filetools.C b/src/support/filetools.C index 29eaeaf4bf..29c548aa69 100644 --- a/src/support/filetools.C +++ b/src/support/filetools.C @@ -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 "/some_script". + string::size_type const size_replace = size_script + 4; + command.replace(pos1, size_replace, QuoteName(script)); + } + + return command; } diff --git a/src/support/filetools.h b/src/support/filetools.h index e62e3431e1..f5d6dafac5 100644 --- a/src/support/filetools.h +++ b/src/support/filetools.h @@ -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); diff --git a/src/support/forkedcall.C b/src/support/forkedcall.C index 93e2d634ee..eff8182530 100644 --- a/src/support/forkedcall.C +++ b/src/support/forkedcall.C @@ -35,6 +35,7 @@ #include +#include #include #include #include @@ -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 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::iterator it = vec.begin(); + vector::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 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::iterator ait = argv.begin(); + vector::iterator const aend = argv.end(); + lyxerr << "\n"; + for (; ait != aend; ++ait) + if (*ait) + lyxerr << '\t'<< *ait << '\n'; + lyxerr << "" << 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; }