ad549adecb
...so that it works on Windows.
504 lines
17 KiB
C++
504 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* 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
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
#include "sal/config.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include "boost/noncopyable.hpp"
|
|
#include "osl/file.h"
|
|
#include "osl/file.hxx"
|
|
#include "osl/process.h"
|
|
#include "osl/thread.h"
|
|
#include "rtl/oustringostreaminserter.hxx"
|
|
#include "rtl/string.h"
|
|
#include "rtl/string.hxx"
|
|
#include "rtl/textcvt.h"
|
|
#include "rtl/ustrbuf.hxx"
|
|
#include "rtl/ustring.h"
|
|
#include "rtl/ustring.hxx"
|
|
#include "sal/macros.h"
|
|
#include "sal/main.h"
|
|
#include "sal/types.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace {
|
|
|
|
namespace global {
|
|
|
|
std::ofstream output;
|
|
|
|
}
|
|
|
|
rtl::OUString getEnvironment(rtl::OUString const & variable) {
|
|
rtl::OUString value;
|
|
if (osl_getEnvironment(variable.pData, &value.pData) != osl_Process_E_None)
|
|
{
|
|
std::cerr
|
|
<< "Error: cannot get environment variable " << variable << '\n';
|
|
throw false; //TODO
|
|
}
|
|
return value;
|
|
}
|
|
|
|
class TempFile: private boost::noncopyable {
|
|
public:
|
|
TempFile() {
|
|
if (osl::FileBase::createTempFile(0, 0, &url_) != osl::FileBase::E_None)
|
|
{
|
|
std::cerr << "osl::FileBase::createTempFile() failed\n";
|
|
throw false; //TODO
|
|
}
|
|
}
|
|
|
|
~TempFile() {
|
|
if (osl::File::remove(url_) != osl::FileBase::E_None) {
|
|
std::cerr << "Warning: failure removing temporary " << url_ << '\n';
|
|
}
|
|
}
|
|
|
|
rtl::OUString getUrl() const { return url_; }
|
|
|
|
private:
|
|
rtl::OUString url_;
|
|
};
|
|
|
|
struct AsciiString {
|
|
char const * string;
|
|
sal_Int32 length;
|
|
};
|
|
|
|
bool matchList(
|
|
rtl::OUString const & url, AsciiString const * list, std::size_t length)
|
|
{
|
|
for (std::size_t i = 0; i != length; ++i) {
|
|
if (url.endsWithAsciiL(list[i].string, list[i].length)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool passesNegativeList(rtl::OUString const & url) {
|
|
static AsciiString const list[] = {
|
|
{ RTL_CONSTASCII_STRINGPARAM("/dictionaries.xcu") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/dictionaries/da_DK/help/da/"
|
|
"org.openoffice.da.hunspell.dictionaries/page1.xhp") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/dictionaries/hu_HU/help/hu/"
|
|
"org.openoffice.hu.hunspell.dictionaries/page1.xhp") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/hidother.src") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/officecfg/registry/data/org/openoffice/Office/"
|
|
"Accelerators.xcu") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/officecfg/registry/data/org/openoffice/Office/Labels.xcu") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/officecfg/registry/data/org/openoffice/Office/SFX.xcu") }
|
|
};
|
|
return !matchList(url, list, SAL_N_ELEMENTS(list));
|
|
}
|
|
|
|
bool passesPositiveList(rtl::OUString const & url) {
|
|
static AsciiString const list[] = {
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_DataLabel_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_ErrorBar_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_LegendPosition_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/"
|
|
"res_SecondaryAxisCheckBoxes_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_Statistic_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_Titlesx_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/chart2/source/controller/menu/MenuItems_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/dbaccess/source/ui/dlg/AutoControls_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/dbaccess/source/ui/inc/toolbox_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/description.xml") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/offmgr/inc/offmenu_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/offmgr/source/offapp/intro/intro_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/svx/inc/globlmn_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/svx/source/intro/intro_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM(
|
|
"/svx/source/unodialogs/textconversiondlgs/"
|
|
"chinese_direction_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/swacc_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/swmn_tmpl.hrc") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/toolbox_tmpl.hrc") }
|
|
};
|
|
return matchList(url, list, SAL_N_ELEMENTS(list));
|
|
}
|
|
|
|
void handleCommand(
|
|
rtl::OUString const & project, rtl::OUString const & projectRoot,
|
|
rtl::OUString const & url, rtl::OUString const & executable, bool positive)
|
|
{
|
|
if (positive ? passesPositiveList(url) : passesNegativeList(url)) {
|
|
rtl::OUString inPath;
|
|
if (osl::FileBase::getSystemPathFromFileURL(url, inPath) !=
|
|
osl::FileBase::E_None)
|
|
{
|
|
std::cerr
|
|
<< "osl::FileBase::getSystemPathFromFileURL(" << url
|
|
<< ") failed\n";
|
|
throw false; //TODO
|
|
}
|
|
TempFile temp;
|
|
rtl::OUString outPath;
|
|
if (osl::FileBase::getSystemPathFromFileURL(temp.getUrl(), outPath)
|
|
!= osl::FileBase::E_None)
|
|
{
|
|
std::cerr
|
|
<< "osl::FileBase::getSystemPathFromFileURL(" << temp.getUrl()
|
|
<< ") failed\n";
|
|
throw false; //TODO
|
|
}
|
|
rtl::OUStringBuffer buf(
|
|
getEnvironment(
|
|
rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SOLARVER"))));
|
|
buf.append('/');
|
|
buf.append(
|
|
getEnvironment(
|
|
rtl::OUString(
|
|
RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD"))));
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/bin/"));
|
|
buf.append(executable);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -e -p "));
|
|
buf.append(project);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -r "));
|
|
buf.append(projectRoot);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -i "));
|
|
buf.append(inPath);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -o "));
|
|
buf.append(outPath);
|
|
buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -l en-US"));
|
|
rtl::OString cmd;
|
|
if (!buf.makeStringAndClear().convertToString(
|
|
&cmd, osl_getThreadTextEncoding(),
|
|
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
|
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
|
|
{
|
|
std::cerr << "Error: Cannot convert command from UTF-16\n";
|
|
throw false; //TODO
|
|
}
|
|
if (system(cmd.getStr()) != 0) {
|
|
std::cerr << "Error: Failed to execute " << cmd.getStr() << '\n';
|
|
throw false; //TODO
|
|
}
|
|
rtl::OString outPath8;
|
|
if (!outPath.convertToString(
|
|
&outPath8, osl_getThreadTextEncoding(),
|
|
(RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|
|
| RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
|
|
{
|
|
std::cerr << "Error: Cannot convert pathname from UTF-16\n";
|
|
throw false; //TODO
|
|
}
|
|
std::ifstream in(outPath8.getStr());
|
|
if (!in.is_open()) {
|
|
std::cerr << "Error: Cannot open " << outPath.getStr() << "\n";
|
|
throw false; //TODO
|
|
}
|
|
while (!in.eof())
|
|
{
|
|
std::string s;
|
|
std::getline(in, s);
|
|
if (!s.empty())
|
|
global::output << s << '\n';
|
|
}
|
|
in.close();
|
|
}
|
|
}
|
|
|
|
void handleFile(
|
|
rtl::OUString const & project, rtl::OUString const & projectRoot,
|
|
rtl::OUString const & url)
|
|
{
|
|
struct Command {
|
|
char const * extension;
|
|
sal_Int32 extensionLength;
|
|
char const * executable;
|
|
bool positive;
|
|
};
|
|
static Command const commands[] = {
|
|
{ RTL_CONSTASCII_STRINGPARAM(".src"), "transex3", false },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".hrc"), "transex3", true },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".ulf"), "ulfex", false },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".xcu"), "cfgex", false },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".xrm"), "xrmex", false },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".xml"), "xrmex", true },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".xhp"), "helpex", false },
|
|
{ RTL_CONSTASCII_STRINGPARAM(".properties"), "propex", false } };
|
|
for (std::size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i) {
|
|
if (url.endsWithAsciiL(
|
|
commands[i].extension, commands[i].extensionLength))
|
|
{
|
|
handleCommand(
|
|
project, projectRoot, url,
|
|
rtl::OUString::createFromAscii(commands[i].executable),
|
|
commands[i].positive);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool includeProject(rtl::OUString const & project) {
|
|
static char const * projects[] = {
|
|
"accessibility",
|
|
"avmedia",
|
|
"basctl",
|
|
"basic",
|
|
"chart2",
|
|
"connectivity",
|
|
"cui",
|
|
"dbaccess",
|
|
"desktop",
|
|
"dictionaries",
|
|
"editeng",
|
|
"extensions",
|
|
"filter",
|
|
"forms",
|
|
"formula",
|
|
"fpicker",
|
|
"framework",
|
|
"helpcontent2",
|
|
"instsetoo_native",
|
|
"mysqlc",
|
|
"nlpsolver",
|
|
"officecfg",
|
|
"padmin",
|
|
"readlicense_oo",
|
|
"reportbuilder",
|
|
"reportdesign",
|
|
"sc",
|
|
"scaddins",
|
|
"sccomp",
|
|
"scp2",
|
|
"scripting",
|
|
"sd",
|
|
"sdext",
|
|
"setup_native",
|
|
"sfx2",
|
|
"shell",
|
|
"starmath",
|
|
"svl",
|
|
"svtools",
|
|
"svx",
|
|
"sw",
|
|
"swext",
|
|
"sysui",
|
|
"uui",
|
|
"vcl",
|
|
"wizards",
|
|
"xmlsecurity" };
|
|
for (std::size_t i = 0; i != SAL_N_ELEMENTS(projects); ++i) {
|
|
if (project.equalsAscii(projects[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool excludeDirectory(rtl::OUString const & directory) {
|
|
// Cf. OUTPATH=* in configure.in:
|
|
static AsciiString const excluded[] = {
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxaig") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxand") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxdfly") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxfbsd") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxios") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxkfg") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxlng") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxmac") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxnbsd") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxobsd") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxsog") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxsol") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("unxubt") },
|
|
{ RTL_CONSTASCII_STRINGPARAM("wntmsc") } };
|
|
for (std::size_t i = 0; i != SAL_N_ELEMENTS(excluded); ++i) {
|
|
if (directory.matchAsciiL(excluded[i].string, excluded[i].length)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Handle one directory in the hierarchy.
|
|
///
|
|
/// Ignores symlinks and instead explicitly descends into clone/*, as the
|
|
/// Cygwin symlinks are not supported by osl::Directory on Windows.
|
|
///
|
|
/// @param url the absolute file URL of this directory
|
|
///
|
|
/// @param level 0 if this is either the root directory that contains the
|
|
/// projects or one of the clone/* directories that contain the additional
|
|
/// projects; -1 if this is the clone directory; 1 if this is a project
|
|
/// directory; 2 if this is a directory inside a project
|
|
///
|
|
/// @param project the name of the project (empty and ignored if level <= 0)
|
|
///
|
|
/// @param the relative path back to the project root (empty and ignored if
|
|
/// level <= 0)
|
|
void handleDirectory(
|
|
rtl::OUString const & url, int level, rtl::OUString const & project,
|
|
rtl::OUString const & projectRoot)
|
|
{
|
|
osl::Directory dir(url);
|
|
if (dir.open() != osl::FileBase::E_None) {
|
|
std::cerr
|
|
<< "Error: Cannot open directory: "
|
|
<< rtl::OUStringToOString(url, osl_getThreadTextEncoding()).getStr()
|
|
<< '\n';
|
|
throw false; //TODO
|
|
}
|
|
for (;;) {
|
|
osl::DirectoryItem item;
|
|
osl::FileBase::RC e = dir.getNextItem(item);
|
|
if (e == osl::FileBase::E_NOENT) {
|
|
break;
|
|
}
|
|
if (e != osl::FileBase::E_None) {
|
|
std::cerr << "Error: Cannot read directory\n";
|
|
throw false; //TODO
|
|
}
|
|
osl::FileStatus stat(
|
|
osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName
|
|
| osl_FileStatus_Mask_FileURL);
|
|
if (item.getFileStatus(stat) != osl::FileBase::E_None) {
|
|
std::cerr << "Error: Cannot get file status\n";
|
|
throw false; //TODO
|
|
}
|
|
switch (level) {
|
|
case -1: // the clone directory
|
|
if (stat.getFileType() == osl::FileStatus::Directory) {
|
|
handleDirectory(
|
|
stat.getFileURL(), 0, rtl::OUString(), rtl::OUString());
|
|
}
|
|
break;
|
|
case 0: // a root directory
|
|
if (stat.getFileType() == osl::FileStatus::Directory) {
|
|
if (includeProject(stat.getFileName())) {
|
|
handleDirectory(
|
|
stat.getFileURL(), 1, stat.getFileName(),
|
|
rtl::OUString());
|
|
} else if (stat.getFileName().equalsAsciiL(
|
|
RTL_CONSTASCII_STRINGPARAM("clone")))
|
|
{
|
|
handleDirectory(
|
|
stat.getFileURL(), -1, rtl::OUString(),
|
|
rtl::OUString());
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
if (stat.getFileType() == osl::FileStatus::Directory) {
|
|
if (level == 2 || !excludeDirectory(stat.getFileName())) {
|
|
rtl::OUString pr(projectRoot);
|
|
if (!pr.isEmpty()) {
|
|
pr += rtl::OUString('/');
|
|
}
|
|
pr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".."));
|
|
handleDirectory(stat.getFileURL(), 2, project, pr);
|
|
}
|
|
} else {
|
|
handleFile(project, projectRoot, stat.getFileURL());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
if (dir.close() != osl::FileBase::E_None) {
|
|
std::cerr << "Error: Cannot close directory\n";
|
|
throw false; //TODO
|
|
}
|
|
}
|
|
|
|
void handleProjects(char const * root) {
|
|
rtl::OUString root16;
|
|
if (!rtl_convertStringToUString(
|
|
&root16.pData, root, rtl_str_getLength(root),
|
|
osl_getThreadTextEncoding(),
|
|
(RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
|
|
| RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
|
|
| RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
|
|
{
|
|
std::cerr << "Error: Cannot convert pathname to UTF-16\n";
|
|
throw false; //TODO
|
|
}
|
|
rtl::OUString rootUrl;
|
|
if (osl::FileBase::getFileURLFromSystemPath(root16, rootUrl)
|
|
!= osl::FileBase::E_None)
|
|
{
|
|
std::cerr << "Error: Cannot convert pathname to URL\n";
|
|
throw false; //TODO
|
|
}
|
|
handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString());
|
|
}
|
|
|
|
}
|
|
|
|
SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
|
|
if (argc != 3) {
|
|
std::cerr
|
|
<< ("localize (c)2001 by Sun Microsystems\n\n"
|
|
"As part of the L10N framework, localize extracts en-US\n"
|
|
"strings for translation out of the toplevel modules defined\n"
|
|
"in projects array in l10ntools/source/localize.cxx.\n\n"
|
|
"Syntax: localize <source-root> <outfile>\n");
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
global::output.open(argv[2], std::ios_base::out | std::ios_base::trunc);
|
|
if (!global::output.is_open()) {
|
|
std::cerr << "Error: Cannot append to " << argv[2] << '\n';
|
|
std::exit(EXIT_FAILURE);
|
|
}
|
|
try {
|
|
handleProjects(argv[1]);
|
|
} catch (bool) { //TODO
|
|
return EXIT_FAILURE;
|
|
}
|
|
global::output.close();
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|