1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "sal/config.h"
37 #include "boost/noncopyable.hpp"
39 #include "osl/file.hxx"
40 #include "osl/process.h"
41 #include "osl/thread.h"
42 #include "rtl/oustringostreaminserter.hxx"
43 #include "rtl/string.h"
44 #include "rtl/string.hxx"
45 #include "rtl/textcvt.h"
46 #include "rtl/ustrbuf.hxx"
47 #include "rtl/ustring.h"
48 #include "rtl/ustring.hxx"
49 #include "sal/macros.h"
51 #include "sal/types.h"
63 rtl::OUString
getEnvironment(rtl::OUString
const & variable
) {
65 if (osl_getEnvironment(variable
.pData
, &value
.pData
) != osl_Process_E_None
)
68 << "Error: cannot get environment variable " << variable
<< '\n';
74 class TempFile
: private boost::noncopyable
{
77 if (osl::FileBase::createTempFile(0, 0, &url_
) != osl::FileBase::E_None
)
79 std::cerr
<< "osl::FileBase::createTempFile() failed\n";
85 if (osl::File::remove(url_
) != osl::FileBase::E_None
) {
86 std::cerr
<< "Warning: failure removing temporary " << url_
<< '\n';
90 rtl::OUString
getUrl() const { return url_
; }
102 rtl::OUString
const & url
, AsciiString
const * list
, std::size_t length
)
104 for (std::size_t i
= 0; i
!= length
; ++i
) {
105 if (url
.endsWithAsciiL(list
[i
].string
, list
[i
].length
)) {
112 bool passesNegativeList(rtl::OUString
const & url
) {
113 static AsciiString
const list
[] = {
114 { RTL_CONSTASCII_STRINGPARAM("/dictionaries.xcu") },
115 { RTL_CONSTASCII_STRINGPARAM(
116 "/dictionaries/da_DK/help/da/"
117 "org.openoffice.da.hunspell.dictionaries/page1.xhp") },
118 { RTL_CONSTASCII_STRINGPARAM(
119 "/dictionaries/da_DK/help/da/"
120 "org.openoffice.da.hunspell.dictionaries/page2.xhp") },
121 { RTL_CONSTASCII_STRINGPARAM(
122 "/dictionaries/hu_HU/help/hu/"
123 "org.openoffice.hu.hunspell.dictionaries/page1.xhp") },
124 { RTL_CONSTASCII_STRINGPARAM("/hidother.src") },
125 { RTL_CONSTASCII_STRINGPARAM(
126 "/officecfg/registry/data/org/openoffice/Office/"
127 "Accelerators.xcu") },
128 { RTL_CONSTASCII_STRINGPARAM(
129 "/officecfg/registry/data/org/openoffice/Office/Labels.xcu") },
130 { RTL_CONSTASCII_STRINGPARAM(
131 "/officecfg/registry/data/org/openoffice/Office/SFX.xcu") }
133 return !matchList(url
, list
, SAL_N_ELEMENTS(list
));
136 bool passesPositiveList(rtl::OUString
const & url
) {
137 static AsciiString
const list
[] = {
138 { RTL_CONSTASCII_STRINGPARAM(
139 "/chart2/source/controller/dialogs/res_DataLabel_tmpl.hrc") },
140 { RTL_CONSTASCII_STRINGPARAM(
141 "/chart2/source/controller/dialogs/res_ErrorBar_tmpl.hrc") },
142 { RTL_CONSTASCII_STRINGPARAM(
143 "/chart2/source/controller/dialogs/res_LegendPosition_tmpl.hrc") },
144 { RTL_CONSTASCII_STRINGPARAM(
145 "/chart2/source/controller/dialogs/"
146 "res_SecondaryAxisCheckBoxes_tmpl.hrc") },
147 { RTL_CONSTASCII_STRINGPARAM(
148 "/chart2/source/controller/dialogs/res_Statistic_tmpl.hrc") },
149 { RTL_CONSTASCII_STRINGPARAM(
150 "/chart2/source/controller/dialogs/res_Titlesx_tmpl.hrc") },
151 { RTL_CONSTASCII_STRINGPARAM(
152 "/chart2/source/controller/dialogs/res_Trendline_tmpl.hrc") },
153 { RTL_CONSTASCII_STRINGPARAM(
154 "/chart2/source/controller/menu/MenuItems_tmpl.hrc") },
155 { RTL_CONSTASCII_STRINGPARAM(
156 "/dbaccess/source/ui/dlg/AutoControls_tmpl.hrc") },
157 { RTL_CONSTASCII_STRINGPARAM(
158 "/dbaccess/source/ui/inc/toolbox_tmpl.hrc") },
159 { RTL_CONSTASCII_STRINGPARAM("/description.xml") },
160 { RTL_CONSTASCII_STRINGPARAM("/offmgr/inc/offmenu_tmpl.hrc") },
161 { RTL_CONSTASCII_STRINGPARAM(
162 "/offmgr/source/offapp/intro/intro_tmpl.hrc") },
163 { RTL_CONSTASCII_STRINGPARAM("/svx/inc/globlmn_tmpl.hrc") },
164 { RTL_CONSTASCII_STRINGPARAM("/svx/source/intro/intro_tmpl.hrc") },
165 { RTL_CONSTASCII_STRINGPARAM(
166 "/svx/source/unodialogs/textconversiondlgs/"
167 "chinese_direction_tmpl.hrc") },
168 { RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/swacc_tmpl.hrc") },
169 { RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/swmn_tmpl.hrc") },
170 { RTL_CONSTASCII_STRINGPARAM("/sw/source/ui/inc/toolbox_tmpl.hrc") }
172 return matchList(url
, list
, SAL_N_ELEMENTS(list
));
176 rtl::OUString
const & project
, rtl::OUString
const & projectRoot
,
177 rtl::OUString
const & url
, rtl::OUString
const & executable
, bool positive
)
179 if (positive
? passesPositiveList(url
) : passesNegativeList(url
)) {
180 rtl::OUString inPath
;
181 if (osl::FileBase::getSystemPathFromFileURL(url
, inPath
) !=
182 osl::FileBase::E_None
)
185 << "osl::FileBase::getSystemPathFromFileURL(" << url
190 rtl::OUString outPath
;
191 if (osl::FileBase::getSystemPathFromFileURL(temp
.getUrl(), outPath
)
192 != osl::FileBase::E_None
)
195 << "osl::FileBase::getSystemPathFromFileURL(" << temp
.getUrl()
199 rtl::OUStringBuffer
buf(
201 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SOLARVER"))));
206 RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD"))));
207 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM("/bin/"));
208 buf
.append(executable
);
209 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -e -p "));
211 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -r "));
212 buf
.append(projectRoot
);
213 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -i "));
215 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -o "));
217 buf
.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -l en-US"));
219 if (!buf
.makeStringAndClear().convertToString(
220 &cmd
, osl_getThreadTextEncoding(),
221 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
222 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
224 std::cerr
<< "Error: Cannot convert command from UTF-16\n";
227 if (system(cmd
.getStr()) != 0) {
228 std::cerr
<< "Error: Failed to execute " << cmd
.getStr() << '\n';
231 rtl::OString outPath8
;
232 if (!outPath
.convertToString(
233 &outPath8
, osl_getThreadTextEncoding(),
234 (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
235 | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
)))
237 std::cerr
<< "Error: Cannot convert pathname from UTF-16\n";
240 std::ifstream
in(outPath8
.getStr());
242 std::cerr
<< "Error: Cannot open " << outPath
.getStr() << "\n";
250 global::output
<< s
<< '\n';
257 rtl::OUString
const & project
, rtl::OUString
const & projectRoot
,
258 rtl::OUString
const & url
)
261 char const * extension
;
262 sal_Int32 extensionLength
;
263 char const * executable
;
266 static Command
const commands
[] = {
267 { RTL_CONSTASCII_STRINGPARAM(".src"), "transex3", false },
268 { RTL_CONSTASCII_STRINGPARAM(".hrc"), "transex3", true },
269 { RTL_CONSTASCII_STRINGPARAM(".ulf"), "ulfex", false },
270 { RTL_CONSTASCII_STRINGPARAM(".xcu"), "cfgex", false },
271 { RTL_CONSTASCII_STRINGPARAM(".xrm"), "xrmex", false },
272 { RTL_CONSTASCII_STRINGPARAM(".xml"), "xrmex", true },
273 { RTL_CONSTASCII_STRINGPARAM(".xhp"), "helpex", false },
274 { RTL_CONSTASCII_STRINGPARAM(".properties"), "propex", false } };
275 for (std::size_t i
= 0; i
!= SAL_N_ELEMENTS(commands
); ++i
) {
276 if (url
.endsWithAsciiL(
277 commands
[i
].extension
, commands
[i
].extensionLength
))
280 project
, projectRoot
, url
,
281 rtl::OUString::createFromAscii(commands
[i
].executable
),
282 commands
[i
].positive
);
288 bool includeProject(rtl::OUString
const & project
) {
289 static char const * projects
[] = {
337 for (std::size_t i
= 0; i
!= SAL_N_ELEMENTS(projects
); ++i
) {
338 if (project
.equalsAscii(projects
[i
])) {
345 bool excludeDirectory(rtl::OUString
const & directory
) {
346 // Cf. OUTPATH=* in configure.in:
347 static AsciiString
const excluded
[] = {
348 { RTL_CONSTASCII_STRINGPARAM("callcatcher") },
349 { RTL_CONSTASCII_STRINGPARAM("unxaig") },
350 { RTL_CONSTASCII_STRINGPARAM("unxand") },
351 { RTL_CONSTASCII_STRINGPARAM("unxdfly") },
352 { RTL_CONSTASCII_STRINGPARAM("unxfbsd") },
353 { RTL_CONSTASCII_STRINGPARAM("unxios") },
354 { RTL_CONSTASCII_STRINGPARAM("unxkfg") },
355 { RTL_CONSTASCII_STRINGPARAM("unxlng") },
356 { RTL_CONSTASCII_STRINGPARAM("unxmac") },
357 { RTL_CONSTASCII_STRINGPARAM("unxnbsd") },
358 { RTL_CONSTASCII_STRINGPARAM("unxobsd") },
359 { RTL_CONSTASCII_STRINGPARAM("unxsog") },
360 { RTL_CONSTASCII_STRINGPARAM("unxsol") },
361 { RTL_CONSTASCII_STRINGPARAM("unxubt") },
362 { RTL_CONSTASCII_STRINGPARAM("wntmsc") } };
363 for (std::size_t i
= 0; i
!= SAL_N_ELEMENTS(excluded
); ++i
) {
364 if (directory
.matchAsciiL(excluded
[i
].string
, excluded
[i
].length
)) {
371 /// Handle one directory in the hierarchy.
373 /// Ignores symlinks and instead explicitly descends into clone/* or src/*,
374 /// as the Cygwin symlinks are not supported by osl::Directory on Windows.
376 /// @param url the absolute file URL of this directory
378 /// @param level 0 if this is either the root directory that contains the
379 /// projects or one of the clone/* or src/* directories that contain the
380 /// additional projects; -1 if this is the clone directory; 1 if this
381 /// is a project directory; 2 if this is a directory inside a project
383 /// @param project the name of the project (empty and ignored if level <= 0)
385 /// @param the relative path back to the project root (empty and ignored if
387 void handleDirectory(
388 rtl::OUString
const & url
, int level
, rtl::OUString
const & project
,
389 rtl::OUString
const & projectRoot
)
391 osl::Directory
dir(url
);
392 if (dir
.open() != osl::FileBase::E_None
) {
394 << "Error: Cannot open directory: "
395 << rtl::OUStringToOString(url
, osl_getThreadTextEncoding()).getStr()
400 osl::DirectoryItem item
;
401 osl::FileBase::RC e
= dir
.getNextItem(item
);
402 if (e
== osl::FileBase::E_NOENT
) {
405 if (e
!= osl::FileBase::E_None
) {
406 std::cerr
<< "Error: Cannot read directory\n";
409 osl::FileStatus
stat(
410 osl_FileStatus_Mask_Type
| osl_FileStatus_Mask_FileName
411 | osl_FileStatus_Mask_FileURL
);
412 if (item
.getFileStatus(stat
) != osl::FileBase::E_None
) {
413 std::cerr
<< "Error: Cannot get file status\n";
417 case -1: // the clone or src directory
418 if (stat
.getFileType() == osl::FileStatus::Directory
) {
420 stat
.getFileURL(), 0, rtl::OUString(), rtl::OUString());
423 case 0: // a root directory
424 if (stat
.getFileType() == osl::FileStatus::Directory
) {
425 if (includeProject(stat
.getFileName())) {
427 stat
.getFileURL(), 1, stat
.getFileName(),
429 } else if ( stat
.getFileName() == "clone" || stat
.getFileName() == "src" )
432 stat
.getFileURL(), -1, rtl::OUString(),
438 if (stat
.getFileType() == osl::FileStatus::Directory
) {
439 if (level
== 2 || !excludeDirectory(stat
.getFileName())) {
440 rtl::OUString
pr(projectRoot
);
442 pr
+= rtl::OUString('/');
444 pr
+= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".."));
445 handleDirectory(stat
.getFileURL(), 2, project
, pr
);
448 handleFile(project
, projectRoot
, stat
.getFileURL());
453 if (dir
.close() != osl::FileBase::E_None
) {
454 std::cerr
<< "Error: Cannot close directory\n";
459 void handleProjects(char const * root
) {
460 rtl::OUString root16
;
461 if (!rtl_convertStringToUString(
462 &root16
.pData
, root
, rtl_str_getLength(root
),
463 osl_getThreadTextEncoding(),
464 (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
465 | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
466 | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR
)))
468 std::cerr
<< "Error: Cannot convert pathname to UTF-16\n";
471 rtl::OUString rootUrl
;
472 if (osl::FileBase::getFileURLFromSystemPath(root16
, rootUrl
)
473 != osl::FileBase::E_None
)
475 std::cerr
<< "Error: Cannot convert pathname to URL\n";
478 handleDirectory(rootUrl
, 0, rtl::OUString(), rtl::OUString());
483 SAL_IMPLEMENT_MAIN_WITH_ARGS(argc
, argv
) {
486 << ("localize (c)2001 by Sun Microsystems\n\n"
487 "As part of the L10N framework, localize extracts en-US\n"
488 "strings for translation out of the toplevel modules defined\n"
489 "in projects array in l10ntools/source/localize.cxx.\n\n"
490 "Syntax: localize <source-root> <outfile>\n");
491 std::exit(EXIT_FAILURE
);
493 global::output
.open(argv
[2], std::ios_base::out
| std::ios_base::trunc
);
494 if (!global::output
.is_open()) {
495 std::cerr
<< "Error: Cannot append to " << argv
[2] << '\n';
496 std::exit(EXIT_FAILURE
);
499 handleProjects(argv
[1]);
500 } catch (bool) { //TODO
503 global::output
.close();
507 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */