From 1d5536011ba650388bb6c23ef583349f48a6f87d Mon Sep 17 00:00:00 2001 From: RenĂ© Engelhard Date: Sat, 24 Jan 2009 12:09:06 +0000 Subject: i10000# fix Windows build --- guw/guw.cc | 1378 ---------------------------------------------------------- guw/makefile | 7 - 2 files changed, 1385 deletions(-) (limited to 'guw') diff --git a/guw/guw.cc b/guw/guw.cc index 808dc9e52e21..e7748a908ff1 100644 --- a/guw/guw.cc +++ b/guw/guw.cc @@ -587,1384 +587,6 @@ match2s(const string argument, const char *pattern, string &sub1, string &sub2) } -// Replace path entry with myCygpath() version -void rep_subn_cyg(string &argument) -{ - // accept ["']["']:["']["']:... to make the - // $(WRAPCMD) echo 1 ICON $(EMQ)"$(APP1ICON)$(EMQ)" - // work in ?tg_app.mk. - // FIXME: Better would be to use a DOSified $(APP1ICON) there and remove - // the special " treatment here. - const char *pattern = "(^|[;,])[\'\"]?([[:alnum:]_~. +-]*(/[[:alnum:]_~. +-]+)+/?)[\'\"]?([;,]|$)"; - const int subexp = 2; - - int status, pos=0; - regex_t re; - - string repstr; - string::size_type oLen, nLen; - - const int maxsub = subexp+1; // One more than the maximal subexpression - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - while (status == 0) { /* While matches found. */ - // Classical assert() - if (match[subexp].rm_eo == -1) { - Fatal("Nonexisting subexpression specified!"); - } - - oLen = match[subexp].rm_eo - match[subexp].rm_so; - repstr.assign(argument.c_str() + pos + match[subexp].rm_so, oLen); - - // Do not replace with shortpaths - myCygpath(repstr, 0); - nLen = repstr.length(); - - // replace - argument.replace( pos + match[subexp].rm_so, oLen, repstr ); - - /* Substring found between match[0].rm_so and match[0].rm_eo. */ - /* This call to regexec() finds the next match. */ - - pos += match[0].rm_eo + nLen - oLen ; - - // Either the last match did end in ';' or we are at the end of para. - // REG_NOTBOL is not used because we skip over the ';' by using pos. - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - } - - if (status != REG_NOMATCH) { - Fatal("regexec had a problem."); - } - - regfree(&re); -} - -// Replace all occurences of subexpression number "subexp" with "repl" -void rep_subn( string &argument, const char *pattern, int subexp, const char repl) -{ - int status, pos=0; - regex_t re; - - const int maxsub = subexp+1; // One more than the maximal subexpression - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - while (status == 0) { /* While matches found. */ - // Classical assert() - if (match[subexp].rm_eo == -1) { - Fatal("Nonexisting subexpression specified!"); - } - - argument[pos + match[subexp].rm_so] = repl; - - /* Substring found between match[0].rm_so and match[0].rm_eo. */ - /* This call to regexec() finds the next match. */ - pos += match[0].rm_eo; - status = regexec (&re, argument.c_str() + pos, maxsub, match, REG_NOTBOL); - } - - if (status != REG_NOMATCH) { - Fatal("regexec had a problem."); - } - - regfree(&re); -} - -// Replace all char1 with char2 -void rep_char( string &argument, const char from, const char to) -{ - string::size_type loc = 0; - - while ( (loc = argument.find( from, loc )) != string::npos ) { - argument[loc] = to; - } -} -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: guw.cc,v $ - * $Revision: 1.7 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// guw - A wrapper program to execute windows programs with parameters that -// contain cygwin (POSIX) style pathnames. - -// Todo: Add a -? switch to guw to issue a help page. - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - - -using std::string; -using std::list; -using std::vector; -using std::cout; -using std::cerr; -using std::endl; -using std::size_t; - -void init_ignorepara(string command); -bool is_ignorepara(const string ¶); -int winFormat(string ¶); -void do_atcommand(string ¶); -void myCygpath(string &path, int shortname = 1 ); -void replace_cyg_env( void ); -void Fatal( const string text ); - -int match2s(const string argument, const char *pattern, string &sub1, string &sub2); -void rep_subn_cyg(string &argument); -void rep_subn( string &argument, const char *pattern, int subexp, const char repl); -void rep_char( string &argument, const char from, const char to); - -bool debug = false; -bool debug_light = false; - -// The commands are treated case insensitive, the parameters -// are case sensitive. -const string ignorepara[] = { "echo /TEST", - "cl -clr: -Z", - "climaker StarOffice/OpenOffice", - "csc -target:", - "g++ -DLOCAL_RULE_LANGS -DUPD -DMINOR" - " -DBUILD_ID -DSC_INFO_OSVERSION", - "gcc -DUDATA_SO_SUFFIX -DSTATIC_O" - " -DPACKAGE -DU_MAKE", - "lib /OUT: -out: -def: -machine:", - "link /BASE: /COMMENT: /DEBUG: /DLL /ENTRY:" - " /MACHINE: /MAP /NODEFAULTLIB /OPT: /RELEASE" - " /STACK: /SUBSYSTEM: -NODEFAULTLIB:" - " -def: delayload: -implib: -map: -out:", - "rc -D", - "regcomp -env: vnd.sun.star.expand:" - " vnd.openoffice.pymodule: file:", - "regmerge /UCR", - "rsc -DOOO_" }; - -vector ignorepara_vec; - -// environment variables that are "winformatted" when -env is given -const string transformvars[] = { "SOLAR_VERSION", - "SOLARVERSION", - "SOLARVER", - "SRC_ROOT", - "LOCALINI", - "GLOBALINI", - "SOLARENV", - "STAR_INSTPATH", - "STAR_SOLARPATH", - "STAR_PACKMISC", - "STAR_SOLARENVPATH", - "STAR_INITROOT", - "STAR_STANDLST", - "CLASSPATH", - "JAVA_HOME" }; - - -int main(int argc, char **argv) { - - // initialize arglist with arguments - list arglist(argv, argv + argc); - - // Drop the first (filename) argument - arglist.pop_front(); - - // iterarot over cmdline elements - list::iterator ele = arglist.begin(); - - // Allowed switch values - bool conv_cyg_arg = false; - - // Look for switches to guw - // Supported: -env - // -dbg - // -ldbg - while ( !arglist.empty() - && ele!=arglist.end() - && (ele->find("-", 0) == 0) ) { - if (ele->find("-env", 0) == 0) { - if ( conv_cyg_arg ) - Fatal("-env used twice!"); - - conv_cyg_arg = true; - ele = arglist.erase(ele); - continue; - } - else if (ele->find("-dbg", 0) == 0) { - - debug = true; - ele = arglist.erase(ele); - continue; - } - else if (ele->find("-ldbg", 0) == 0) { - - debug_light = true; - ele = arglist.erase(ele); - continue; - } - else { - // Ignore this switch - ++ele; - } - } - - // The next entry must be the program - string command; - if ( !arglist.empty() ) { - command.assign(*arglist.begin()); - arglist.pop_front(); - } - else - Fatal("guw needs at least one parameter."); - - if ( debug ) - cerr << "Command: " << command << "\n" << endl; - // Initialize parameter exception list (for this command) - init_ignorepara(command); - - - // Do something if -env was found - if ( conv_cyg_arg ) - replace_cyg_env(); - - - // loop and and DOSify the parameters - if ( debug ) - cerr << "Transform the parameter\n" << endl; - - ele=arglist.begin(); - while ( ele != arglist.end() ) { - - if ((*ele)[0] == '@') - do_atcommand(*ele); - else if (!is_ignorepara(*ele)) { - if ( debug ) { - cerr << "----------------" << endl; - cerr << "Process parameter: " << *ele << endl; - } - winFormat(*ele); - if ( debug ) - cerr << "Transformed to: " << *ele << "\n" << endl; - } - - ++ele; - } - - // create the argv[] for execvp(argv[0], argv); - ele=arglist.begin(); - - // const char *nargv[arglist.size()+2]; // or .. - char *nargv[arglist.size()+2]; - - // nargv[0] = command.c_str(); // or .. - nargv[0] = new char[command.length()+1]; - // strcpy(nargv[0], command.c_str()); - command.copy(nargv[0], command.length()); - nargv[0][command.length()] = 0; - - if ( debug ) - cerr << "----------------\n" << endl; - if ( debug || debug_light ) - cerr << "Execute: " << nargv[0]; - - int count = 1, sLen; - while ( ele != arglist.end() ) { - // nargv[count] = ele->c_str(); // or .. - sLen = ele->length(); - nargv[count] = new char[sLen+1]; - // strcpy(nargv[count], ele->c_str()); - ele->copy(nargv[count], sLen); - nargv[count][sLen] = 0; - - if ( debug || debug_light ) - cerr << " " << nargv[count]; - - ++count; - ++ele; - } - // last nargv[] must be NULL - nargv[count] = NULL; - if ( debug || debug_light ) - cerr << endl; - - // Unfortunately the prototype of execvp does not like const char*, - // actually not const char* nargv[] coming from .c_str(). So either - // we copy everything into newly allocated variables or we force it - // with a cast. const_cast() - // execvp(nargv[0], const_cast(nargv) ); - if ( execvp(nargv[0], nargv ) < 0 ) { - perror("Execvp error. Aborting."); - exit(1); - } - - // Omit the deleting of the dynamically allocated nargv[] elements - // here as this part will never be reached. - - return 0; -} - -// Initialize exception list from global var ignorepara[] -void init_ignorepara(string fullcommand) { - const size_t kplen = sizeof(ignorepara)/sizeof(string *); - string shortcommand, cmd, para, sub2; - - // First lowercase everything - for(size_t i=0;i 4 && fullcommand.rfind(".exe") == slen - 4 ) - fullcommand.erase(slen-4); - - // get the program name - Only one subexpression - if (!match2s(fullcommand, "([[:alnum:]_~. +-]+)$", - shortcommand, sub2)) { - Fatal("No basename found in: " + fullcommand); - } - - for (size_t i=0; i != kplen; ++i) { - std::istringstream line(ignorepara[i]); - line >> cmd; - if (shortcommand == cmd) - while (line >> para) { - ignorepara_vec.push_back(para); - } - } - return ; -} - -// Check if command/parameter is in exception list. -bool is_ignorepara(const string ¶) { - - for( vector::iterator it = ignorepara_vec.begin(); - it != ignorepara_vec.end(); it++ ) { - if ( para.find(*it) != string::npos ) { - if ( debug ) - cerr << "Found execption para: " << para << endl; - - return true; - } - } - - return false; -} - -// Reformat para to DOSish format -int winFormat(string ¶) { - string su1, su2; - - // Instead of ([/[:alnum:]_~. +-]+) use ((/?[[:alnum:]_~. +-]+)+) - - // find [-][-]X=, sometimes with quotes or "/" at the end - if (match2s(para, "^(-?-?[[:alpha:]][[:alnum:]_.-]*=)[\'\"]?((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - ([-][-]=)\n" - << " " << para << endl; - - } - // find -X:, sometimes with quotes or "/" at the end - else if (match2s(para, "^(-[[:alpha:]][[:alnum:]_.]*:)[\'\"]?((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-:)\n" - << " " << para << endl; - - } - // find -X:, and prevents translating of these. - else if (match2s(para, "^(-[[:alpha:]][[:alnum:]_]*:)(.*)$", - su1, su2)) { - - // myCygpath(su2); - // para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-:)\n" - << " " << para << endl; - - } - // See iz35982 for the reason for the special treatment of this switch. - // This regex evaluates :///, sometimes with - // quotes or "/" at the end - else if (match2s(para, "^([[:alpha:]][[:alnum:]_]*:)[\'\"]?///((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + "///" + su2); - // Replace \ to / - rep_char( para, '\\', '/'); - - if ( debug ) - cerr << " WinFormat - (:///)\n" - << " " << para << endl; - - } - // find -X, sometimes with quotes or "/" at the end - else if (match2s(para, "^(-[[:alpha:]])[\'\"]?((/[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-X)\n" - << " " << para << endl; - - } - // find -FX (MSVC switches for output naming), sometimes with quotes - // or "/" at the end - else if (match2s(para, "^(-F[ARdemopr])[\'\"]?(/[/[:alnum:]_~. +-]+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (compiler naming (-FX) path)\n" - << " " << para << endl; - - } - else{ - // No parameter found, assume a path - - // replace the colon in drives with 0x1F" - // (Unused ascii US - unit separator) - rep_subn( para, "(^|[;,])[[:alpha:]](:)", 2, 0x1F); - - // Replace remaining : to ; - rep_char( para, ':', ';'); - - // Replace back US to ':'; - rep_char( para, 0x1F, ':'); - - /* Search for posix path ;entry; (The regex accepts valid paths with at - * least one /) and replace with DOS path, accept quotes. - * since iz28717 we also accept ',' as path seperator. */ - rep_subn_cyg(para); - - if ( debug ) - cerr << " WinFormat - full path\n" - << " " << para << endl; - - } - - // Sanity check for -X - if (match2s(para, "^(-[[:alpha:]])[\'\"]?((/[[:alnum:]_~. +-]+)+)", - su1, su2)) { - Fatal("Not converted -X/... type switch in :" + para); - } - // Sanity check for [-]X(:|=) case - if (match2s(para, "^(-?[[:alpha:]][[:alnum:]_.]+[=:])[\'\"]?((/[[:alnum:]_~. +-]+)+)", - su1, su2)) { - Fatal("Not processed [-]X(=|:)/... in :" + para); - } - - - return 1; -} - -// Reformat para to DOSish format -void do_atcommand(string ¶) { - string at, filename, token; - - // Workaround, iz28717, keep number of @'s. - match2s(para, "^(@+)(.*)",at ,filename); - if ( debug ) { - cerr << "----------------" << endl; - cerr << "Process @-file" << endl; - cerr << " :" << at << ": before filename :" << filename << ":" << endl; - } - - // Read at file into memory - std::ifstream atin(filename.c_str()); - list newtoken; - while (atin >> token) { - // Read / transform tokens - if ( debug ) - cerr << "@ token :" << token << ":" << endl; - if (!is_ignorepara(token)) - winFormat(token); - - newtoken.push_back(token); - } - atin.close(); - - // Write token tokens bak to file - if ( debug || debug_light ) - cerr << "New @-file parameter:" << endl; - - // for debugging .. - // filename += ".bak"; - - std::ofstream atout(filename.c_str()); - list::iterator tok = newtoken.begin(); - while ( tok != newtoken.end() ) { - if ( debug || debug_light ) - cerr << ( tok != newtoken.begin() ? " " : "" ) << *tok ; - - atout << ( tok != newtoken.begin() ? " " : "" ) << *tok ; - ++tok; - } - // We want a dos file - atout << '\r' << endl; - atout.close(); - - // Transform the filename - winFormat(filename); - para = at + filename; - if ( debug || debug_light ) { - cerr << "\nNew @-file name: " << para << "\n" << endl; - } -} - -void myCygpath(string &path, int shortname /* =1 */ ) -{ - static char convpath[MAX_PATH]; - static char buf[MAX_PATH]; - int err; - - // Only use cygwin_conv_to_win32_path() on absolute paths as it errors - // out if its path doen't exist. Unfortunatelt there are a lot of not - // existing relative pathes used as parameters during an OOo build. - if( path.find("/", 0) == 0) { - err = cygwin_conv_to_win32_path( path.c_str(), convpath ); - } - else { - rep_char( path, '/', '\\'); - // see below, we copy convpath back to path, that's stupid - path.copy( convpath, path.length()); - convpath[path.length()] = 0; - err = 0; - } - - if (err) - Fatal("converting: " + path + " - " + strerror(errno) ); - - // Only convert to short dos names when space is present - if (shortname && (path.find(" ", 0) != string::npos) ) { - DWORD len = GetShortPathName (convpath, buf, MAX_PATH); - if (!len) { - Fatal("cannot create short name of " + string(convpath) ); - } - - path.assign(buf); - } - else - path.assign(convpath); - -} - -void replace_cyg_env( void ) { - // Transform certain environment variables - if ( debug ) - cerr << "Transforming some environment variables" << endl; - - const size_t nvars = sizeof(transformvars)/sizeof(string *); - - char *currvar; - string newvar; - - for (size_t i=0; i != nvars; ++i) { - if ( currvar = getenv(transformvars[i].c_str() ) ) { - // Only transform existent vars - if ( debug ) - cerr << "Transform variable: " << transformvars[i] << "=" - << currvar << endl; - newvar.assign(currvar); - winFormat(newvar); - if( setenv(transformvars[i].c_str(), newvar.c_str(), 1) ) - Fatal("setenv failed on " + transformvars[i] + "=" + newvar + - " with error: " + strerror(errno)); - if ( debug ) - cerr << "To: " << transformvars[i] << "=" - << newvar << "\n" << endl; - } - } -} - - -void Fatal( const string text ) { - // End with error - cerr << "Error: " << text << endl; - exit(1); -} - - -int -match2s(const string argument, const char *pattern, string &sub1, string &sub2) -{ - int status; - regex_t re; - - const int maxsub = 3; // Only 3 needed, 4 is for debug - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec(&re, argument.c_str(), maxsub, match, 0); - regfree(&re); - - if (status == REG_NOMATCH) { - return(0); /* no match */ - } else if (status == 0) { - string tstr(argument.c_str() + match[0].rm_so, - match[0].rm_eo - match[0].rm_so); - // cout << "Match: " << tstr << endl; - - sub1.assign(argument.c_str() + match[1].rm_so, match[1].rm_eo - match[1].rm_so); - // cout << "Match1: " << sub1 << endl; - - sub2.assign(argument.c_str() + match[2].rm_so, match[2].rm_eo - match[2].rm_so); - // cout << "Match2: " << sub2 << endl; - - return(1); /* match found */ - } else { - Fatal("regexec had a problem."); - } - - // Not reached. - return(1); -} - - -// Replace path entry with myCygpath() version -void rep_subn_cyg(string &argument) -{ - // accept ["']["']:["']["']:... to make the - // $(WRAPCMD) echo 1 ICON $(EMQ)"$(APP1ICON)$(EMQ)" - // work in ?tg_app.mk. - // FIXME: Better would be to use a DOSified $(APP1ICON) there and remove - // the special " treatment here. - const char *pattern = "(^|[;,])[\'\"]?([[:alnum:]_~. +-]*(/[[:alnum:]_~. +-]+)+/?)[\'\"]?([;,]|$)"; - const int subexp = 2; - - int status, pos=0; - regex_t re; - - string repstr; - string::size_type oLen, nLen; - - const int maxsub = subexp+1; // One more than the maximal subexpression - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - while (status == 0) { /* While matches found. */ - // Classical assert() - if (match[subexp].rm_eo == -1) { - Fatal("Nonexisting subexpression specified!"); - } - - oLen = match[subexp].rm_eo - match[subexp].rm_so; - repstr.assign(argument.c_str() + pos + match[subexp].rm_so, oLen); - - // Do not replace with shortpaths - myCygpath(repstr, 0); - nLen = repstr.length(); - - // replace - argument.replace( pos + match[subexp].rm_so, oLen, repstr ); - - /* Substring found between match[0].rm_so and match[0].rm_eo. */ - /* This call to regexec() finds the next match. */ - - pos += match[0].rm_eo + nLen - oLen ; - - // Either the last match did end in ';' or we are at the end of para. - // REG_NOTBOL is not used because we skip over the ';' by using pos. - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - } - - if (status != REG_NOMATCH) { - Fatal("regexec had a problem."); - } - - regfree(&re); -} - -// Replace all occurences of subexpression number "subexp" with "repl" -void rep_subn( string &argument, const char *pattern, int subexp, const char repl) -{ - int status, pos=0; - regex_t re; - - const int maxsub = subexp+1; // One more than the maximal subexpression - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec (&re, argument.c_str() + pos, maxsub, match, 0); - while (status == 0) { /* While matches found. */ - // Classical assert() - if (match[subexp].rm_eo == -1) { - Fatal("Nonexisting subexpression specified!"); - } - - argument[pos + match[subexp].rm_so] = repl; - - /* Substring found between match[0].rm_so and match[0].rm_eo. */ - /* This call to regexec() finds the next match. */ - pos += match[0].rm_eo; - status = regexec (&re, argument.c_str() + pos, maxsub, match, REG_NOTBOL); - } - - if (status != REG_NOMATCH) { - Fatal("regexec had a problem."); - } - - regfree(&re); -} - -// Replace all char1 with char2 -void rep_char( string &argument, const char from, const char to) -{ - string::size_type loc = 0; - - while ( (loc = argument.find( from, loc )) != string::npos ) { - argument[loc] = to; - } -} -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2008 by Sun Microsystems, Inc. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * $RCSfile: guw.cc,v $ - * $Revision: 1.7 $ - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org 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 Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// guw - A wrapper program to execute windows programs with parameters that -// contain cygwin (POSIX) style pathnames. - -// Todo: Add a -? switch to guw to issue a help page. - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - - -using std::string; -using std::list; -using std::vector; -using std::cout; -using std::cerr; -using std::endl; -using std::size_t; - -void init_ignorepara(string command); -bool is_ignorepara(const string ¶); -int winFormat(string ¶); -void do_atcommand(string ¶); -void myCygpath(string &path, int shortname = 1 ); -void replace_cyg_env( void ); -void Fatal( const string text ); - -int match2s(const string argument, const char *pattern, string &sub1, string &sub2); -void rep_subn_cyg(string &argument); -void rep_subn( string &argument, const char *pattern, int subexp, const char repl); -void rep_char( string &argument, const char from, const char to); - -bool debug = false; -bool debug_light = false; - -// The commands are treated case insensitive, the parameters -// are case sensitive. -const string ignorepara[] = { "echo /TEST", - "cl -clr: -Z", - "climaker StarOffice/OpenOffice", - "csc -target:", - "g++ -DLOCAL_RULE_LANGS -DUPD -DMINOR" - " -DBUILD_ID -DSC_INFO_OSVERSION", - "gcc -DUDATA_SO_SUFFIX -DSTATIC_O" - " -DPACKAGE -DU_MAKE", - "lib /OUT: -out: -def: -machine:", - "link /BASE: /COMMENT: /DEBUG: /DLL /ENTRY:" - " /MACHINE: /MAP /NODEFAULTLIB /OPT: /RELEASE" - " /STACK: /SUBSYSTEM: -NODEFAULTLIB:" - " -def: delayload: -implib: -map: -out:", - "rc -D", - "regcomp -env: vnd.sun.star.expand:" - " vnd.openoffice.pymodule: file:", - "regmerge /UCR", - "rsc -DOOO_" }; - -vector ignorepara_vec; - -// environment variables that are "winformatted" when -env is given -const string transformvars[] = { "SOLAR_VERSION", - "SOLARVERSION", - "SOLARVER", - "SRC_ROOT", - "LOCALINI", - "GLOBALINI", - "SOLARENV", - "STAR_INSTPATH", - "STAR_SOLARPATH", - "STAR_PACKMISC", - "STAR_SOLARENVPATH", - "STAR_INITROOT", - "STAR_STANDLST", - "CLASSPATH", - "JAVA_HOME" }; - - -int main(int argc, char **argv) { - - // initialize arglist with arguments - list arglist(argv, argv + argc); - - // Drop the first (filename) argument - arglist.pop_front(); - - // iterarot over cmdline elements - list::iterator ele = arglist.begin(); - - // Allowed switch values - bool conv_cyg_arg = false; - - // Look for switches to guw - // Supported: -env - // -dbg - // -ldbg - while ( !arglist.empty() - && ele!=arglist.end() - && (ele->find("-", 0) == 0) ) { - if (ele->find("-env", 0) == 0) { - if ( conv_cyg_arg ) - Fatal("-env used twice!"); - - conv_cyg_arg = true; - ele = arglist.erase(ele); - continue; - } - else if (ele->find("-dbg", 0) == 0) { - - debug = true; - ele = arglist.erase(ele); - continue; - } - else if (ele->find("-ldbg", 0) == 0) { - - debug_light = true; - ele = arglist.erase(ele); - continue; - } - else { - // Ignore this switch - ++ele; - } - } - - // The next entry must be the program - string command; - if ( !arglist.empty() ) { - command.assign(*arglist.begin()); - arglist.pop_front(); - } - else - Fatal("guw needs at least one parameter."); - - if ( debug ) - cerr << "Command: " << command << "\n" << endl; - // Initialize parameter exception list (for this command) - init_ignorepara(command); - - - // Do something if -env was found - if ( conv_cyg_arg ) - replace_cyg_env(); - - - // loop and and DOSify the parameters - if ( debug ) - cerr << "Transform the parameter\n" << endl; - - ele=arglist.begin(); - while ( ele != arglist.end() ) { - - if ((*ele)[0] == '@') - do_atcommand(*ele); - else if (!is_ignorepara(*ele)) { - if ( debug ) { - cerr << "----------------" << endl; - cerr << "Process parameter: " << *ele << endl; - } - winFormat(*ele); - if ( debug ) - cerr << "Transformed to: " << *ele << "\n" << endl; - } - - ++ele; - } - - // create the argv[] for execvp(argv[0], argv); - ele=arglist.begin(); - - // const char *nargv[arglist.size()+2]; // or .. - char *nargv[arglist.size()+2]; - - // nargv[0] = command.c_str(); // or .. - nargv[0] = new char[command.length()+1]; - // strcpy(nargv[0], command.c_str()); - command.copy(nargv[0], command.length()); - nargv[0][command.length()] = 0; - - if ( debug ) - cerr << "----------------\n" << endl; - if ( debug || debug_light ) - cerr << "Execute: " << nargv[0]; - - int count = 1, sLen; - while ( ele != arglist.end() ) { - // nargv[count] = ele->c_str(); // or .. - sLen = ele->length(); - nargv[count] = new char[sLen+1]; - // strcpy(nargv[count], ele->c_str()); - ele->copy(nargv[count], sLen); - nargv[count][sLen] = 0; - - if ( debug || debug_light ) - cerr << " " << nargv[count]; - - ++count; - ++ele; - } - // last nargv[] must be NULL - nargv[count] = NULL; - if ( debug || debug_light ) - cerr << endl; - - // Unfortunately the prototype of execvp does not like const char*, - // actually not const char* nargv[] coming from .c_str(). So either - // we copy everything into newly allocated variables or we force it - // with a cast. const_cast() - // execvp(nargv[0], const_cast(nargv) ); - if ( execvp(nargv[0], nargv ) < 0 ) { - perror("Execvp error. Aborting."); - exit(1); - } - - // Omit the deleting of the dynamically allocated nargv[] elements - // here as this part will never be reached. - - return 0; -} - -// Initialize exception list from global var ignorepara[] -void init_ignorepara(string fullcommand) { - const size_t kplen = sizeof(ignorepara)/sizeof(string *); - string shortcommand, cmd, para, sub2; - - // First lowercase everything - for(size_t i=0;i 4 && fullcommand.rfind(".exe") == slen - 4 ) - fullcommand.erase(slen-4); - - // get the program name - Only one subexpression - if (!match2s(fullcommand, "([[:alnum:]_~. +-]+)$", - shortcommand, sub2)) { - Fatal("No basename found in: " + fullcommand); - } - - for (size_t i=0; i != kplen; ++i) { - std::istringstream line(ignorepara[i]); - line >> cmd; - if (shortcommand == cmd) - while (line >> para) { - ignorepara_vec.push_back(para); - } - } - return ; -} - -// Check if command/parameter is in exception list. -bool is_ignorepara(const string ¶) { - - for( vector::iterator it = ignorepara_vec.begin(); - it != ignorepara_vec.end(); it++ ) { - if ( para.find(*it) != string::npos ) { - if ( debug ) - cerr << "Found execption para: " << para << endl; - - return true; - } - } - - return false; -} - -// Reformat para to DOSish format -int winFormat(string ¶) { - string su1, su2; - - // Instead of ([/[:alnum:]_~. +-]+) use ((/?[[:alnum:]_~. +-]+)+) - - // find [-][-]X=, sometimes with quotes or "/" at the end - if (match2s(para, "^(-?-?[[:alpha:]][[:alnum:]_.-]*=)[\'\"]?((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - ([-][-]=)\n" - << " " << para << endl; - - } - // find -X:, sometimes with quotes or "/" at the end - else if (match2s(para, "^(-[[:alpha:]][[:alnum:]_.]*:)[\'\"]?((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-:)\n" - << " " << para << endl; - - } - // find -X:, and prevents translating of these. - else if (match2s(para, "^(-[[:alpha:]][[:alnum:]_]*:)(.*)$", - su1, su2)) { - - // myCygpath(su2); - // para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-:)\n" - << " " << para << endl; - - } - // See iz35982 for the reason for the special treatment of this switch. - // This regex evaluates :///, sometimes with - // quotes or "/" at the end - else if (match2s(para, "^([[:alpha:]][[:alnum:]_]*:)[\'\"]?///((/?[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + "///" + su2); - // Replace \ to / - rep_char( para, '\\', '/'); - - if ( debug ) - cerr << " WinFormat - (:///)\n" - << " " << para << endl; - - } - // find -X, sometimes with quotes or "/" at the end - else if (match2s(para, "^(-[[:alpha:]])[\'\"]?((/[[:alnum:]_~. +-]+)+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (-X)\n" - << " " << para << endl; - - } - // find -FX (MSVC switches for output naming), sometimes with quotes - // or "/" at the end - else if (match2s(para, "^(-F[ARdemopr])[\'\"]?(/[/[:alnum:]_~. +-]+)[\'\"]?$", - su1, su2)) { - - myCygpath(su2); - para.assign(su1 + su2); - if ( debug ) - cerr << " WinFormat - (compiler naming (-FX) path)\n" - << " " << para << endl; - - } - else{ - // No parameter found, assume a path - - // replace the colon in drives with 0x1F" - // (Unused ascii US - unit separator) - rep_subn( para, "(^|[;,])[[:alpha:]](:)", 2, 0x1F); - - // Replace remaining : to ; - rep_char( para, ':', ';'); - - // Replace back US to ':'; - rep_char( para, 0x1F, ':'); - - /* Search for posix path ;entry; (The regex accepts valid paths with at - * least one /) and replace with DOS path, accept quotes. - * since iz28717 we also accept ',' as path seperator. */ - rep_subn_cyg(para); - - if ( debug ) - cerr << " WinFormat - full path\n" - << " " << para << endl; - - } - - // Sanity check for -X - if (match2s(para, "^(-[[:alpha:]])[\'\"]?((/[[:alnum:]_~. +-]+)+)", - su1, su2)) { - Fatal("Not converted -X/... type switch in :" + para); - } - // Sanity check for [-]X(:|=) case - if (match2s(para, "^(-?[[:alpha:]][[:alnum:]_.]+[=:])[\'\"]?((/[[:alnum:]_~. +-]+)+)", - su1, su2)) { - Fatal("Not processed [-]X(=|:)/... in :" + para); - } - - - return 1; -} - -// Reformat para to DOSish format -void do_atcommand(string ¶) { - string at, filename, token; - - // Workaround, iz28717, keep number of @'s. - match2s(para, "^(@+)(.*)",at ,filename); - if ( debug ) { - cerr << "----------------" << endl; - cerr << "Process @-file" << endl; - cerr << " :" << at << ": before filename :" << filename << ":" << endl; - } - - // Read at file into memory - std::ifstream atin(filename.c_str()); - list newtoken; - while (atin >> token) { - // Read / transform tokens - if ( debug ) - cerr << "@ token :" << token << ":" << endl; - if (!is_ignorepara(token)) - winFormat(token); - - newtoken.push_back(token); - } - atin.close(); - - // Write token tokens bak to file - if ( debug || debug_light ) - cerr << "New @-file parameter:" << endl; - - // for debugging .. - // filename += ".bak"; - - std::ofstream atout(filename.c_str()); - list::iterator tok = newtoken.begin(); - while ( tok != newtoken.end() ) { - if ( debug || debug_light ) - cerr << ( tok != newtoken.begin() ? " " : "" ) << *tok ; - - atout << ( tok != newtoken.begin() ? " " : "" ) << *tok ; - ++tok; - } - // We want a dos file - atout << '\r' << endl; - atout.close(); - - // Transform the filename - winFormat(filename); - para = at + filename; - if ( debug || debug_light ) { - cerr << "\nNew @-file name: " << para << "\n" << endl; - } -} - -void myCygpath(string &path, int shortname /* =1 */ ) -{ - static char convpath[MAX_PATH]; - static char buf[MAX_PATH]; - int err; - - // Only use cygwin_conv_to_win32_path() on absolute paths as it errors - // out if its path doen't exist. Unfortunatelt there are a lot of not - // existing relative pathes used as parameters during an OOo build. - if( path.find("/", 0) == 0) { - err = cygwin_conv_to_win32_path( path.c_str(), convpath ); - } - else { - rep_char( path, '/', '\\'); - // see below, we copy convpath back to path, that's stupid - path.copy( convpath, path.length()); - convpath[path.length()] = 0; - err = 0; - } - - if (err) - Fatal("converting: " + path + " - " + strerror(errno) ); - - // Only convert to short dos names when space is present - if (shortname && (path.find(" ", 0) != string::npos) ) { - DWORD len = GetShortPathName (convpath, buf, MAX_PATH); - if (!len) { - Fatal("cannot create short name of " + string(convpath) ); - } - - path.assign(buf); - } - else - path.assign(convpath); - -} - -void replace_cyg_env( void ) { - // Transform certain environment variables - if ( debug ) - cerr << "Transforming some environment variables" << endl; - - const size_t nvars = sizeof(transformvars)/sizeof(string *); - - char *currvar; - string newvar; - - for (size_t i=0; i != nvars; ++i) { - if ( currvar = getenv(transformvars[i].c_str() ) ) { - // Only transform existent vars - if ( debug ) - cerr << "Transform variable: " << transformvars[i] << "=" - << currvar << endl; - newvar.assign(currvar); - winFormat(newvar); - if( setenv(transformvars[i].c_str(), newvar.c_str(), 1) ) - Fatal("setenv failed on " + transformvars[i] + "=" + newvar + - " with error: " + strerror(errno)); - if ( debug ) - cerr << "To: " << transformvars[i] << "=" - << newvar << "\n" << endl; - } - } -} - - -void Fatal( const string text ) { - // End with error - cerr << "Error: " << text << endl; - exit(1); -} - - -int -match2s(const string argument, const char *pattern, string &sub1, string &sub2) -{ - int status; - regex_t re; - - const int maxsub = 3; // Only 3 needed, 4 is for debug - regmatch_t match[maxsub]; - - if (regcomp(&re, pattern, REG_EXTENDED) != 0) { - Fatal("regcomp had a problem."); /* report error */ - } - status = regexec(&re, argument.c_str(), maxsub, match, 0); - regfree(&re); - - if (status == REG_NOMATCH) { - return(0); /* no match */ - } else if (status == 0) { - string tstr(argument.c_str() + match[0].rm_so, - match[0].rm_eo - match[0].rm_so); - // cout << "Match: " << tstr << endl; - - sub1.assign(argument.c_str() + match[1].rm_so, match[1].rm_eo - match[1].rm_so); - // cout << "Match1: " << sub1 << endl; - - sub2.assign(argument.c_str() + match[2].rm_so, match[2].rm_eo - match[2].rm_so); - // cout << "Match2: " << sub2 << endl; - - return(1); /* match found */ - } else { - Fatal("regexec had a problem."); - } - - // Not reached. - return(1); -} - - // Replace path entry with myCygpath() version void rep_subn_cyg(string &argument) { diff --git a/guw/makefile b/guw/makefile index c8f24e6ddbb2..8931c32f81a0 100644 --- a/guw/makefile +++ b/guw/makefile @@ -2,11 +2,4 @@ sources = guw.cc guw : $(sources) g++ -Wall -o guw $(sources) -sources = guw.cc -guw : $(sources) - g++ -Wall -o guw $(sources) -sources = guw.cc - -guw : $(sources) - g++ -Wall -o guw $(sources) -- cgit