Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "sal/config.h"
30 : :
31 : : #include <cstddef>
32 : : #include <cstdlib>
33 : : #include <fstream>
34 : : #include <iostream>
35 : : #include <string>
36 : :
37 : : #include "boost/noncopyable.hpp"
38 : : #include "osl/file.h"
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"
50 : : #include "sal/main.h"
51 : : #include "sal/types.h"
52 : :
53 : : using namespace std;
54 : :
55 : : namespace {
56 : :
57 : : namespace global {
58 : :
59 : 0 : std::ofstream output;
60 : :
61 : : }
62 : :
63 : 0 : rtl::OUString getEnvironment(rtl::OUString const & variable) {
64 : 0 : rtl::OUString value;
65 : 0 : if (osl_getEnvironment(variable.pData, &value.pData) != osl_Process_E_None)
66 : : {
67 : : std::cerr
68 : 0 : << "Error: cannot get environment variable " << variable << '\n';
69 : 0 : throw false; //TODO
70 : : }
71 : 0 : return value;
72 : : }
73 : :
74 : : class TempFile: private boost::noncopyable {
75 : : public:
76 : 0 : TempFile() {
77 : 0 : if (osl::FileBase::createTempFile(0, 0, &url_) != osl::FileBase::E_None)
78 : : {
79 : 0 : std::cerr << "osl::FileBase::createTempFile() failed\n";
80 : 0 : throw false; //TODO
81 : : }
82 : 0 : }
83 : :
84 : 0 : ~TempFile() {
85 : 0 : if (osl::File::remove(url_) != osl::FileBase::E_None) {
86 : 0 : std::cerr << "Warning: failure removing temporary " << url_ << '\n';
87 : : }
88 : 0 : }
89 : :
90 : 0 : rtl::OUString getUrl() const { return url_; }
91 : :
92 : : private:
93 : : rtl::OUString url_;
94 : : };
95 : :
96 : : struct AsciiString {
97 : : char const * string;
98 : : sal_Int32 length;
99 : : };
100 : :
101 : 0 : bool matchList(
102 : : rtl::OUString const & url, AsciiString const * list, std::size_t length)
103 : : {
104 : 0 : for (std::size_t i = 0; i != length; ++i) {
105 : 0 : if (url.endsWithAsciiL(list[i].string, list[i].length)) {
106 : 0 : return true;
107 : : }
108 : : }
109 : 0 : return false;
110 : : }
111 : :
112 : 0 : 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") }
132 : : };
133 : 0 : return !matchList(url, list, SAL_N_ELEMENTS(list));
134 : : }
135 : :
136 : 0 : 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") }
171 : : };
172 : 0 : return matchList(url, list, SAL_N_ELEMENTS(list));
173 : : }
174 : :
175 : 0 : void handleCommand(
176 : : rtl::OUString const & project, rtl::OUString const & projectRoot,
177 : : rtl::OUString const & url, rtl::OUString const & executable, bool positive)
178 : : {
179 : 0 : if (positive ? passesPositiveList(url) : passesNegativeList(url)) {
180 : 0 : rtl::OUString inPath;
181 : 0 : if (osl::FileBase::getSystemPathFromFileURL(url, inPath) !=
182 : : osl::FileBase::E_None)
183 : : {
184 : : std::cerr
185 : 0 : << "osl::FileBase::getSystemPathFromFileURL(" << url
186 : 0 : << ") failed\n";
187 : 0 : throw false; //TODO
188 : : }
189 : 0 : TempFile temp;
190 : 0 : rtl::OUString outPath;
191 : 0 : if (osl::FileBase::getSystemPathFromFileURL(temp.getUrl(), outPath)
192 : : != osl::FileBase::E_None)
193 : : {
194 : : std::cerr
195 : 0 : << "osl::FileBase::getSystemPathFromFileURL(" << temp.getUrl()
196 : 0 : << ") failed\n";
197 : 0 : throw false; //TODO
198 : : }
199 : : rtl::OUStringBuffer buf(
200 : : getEnvironment(
201 : 0 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SOLARVER"))));
202 : 0 : buf.append('/');
203 : : buf.append(
204 : : getEnvironment(
205 : : rtl::OUString(
206 : 0 : RTL_CONSTASCII_USTRINGPARAM("INPATH_FOR_BUILD"))));
207 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM("/bin/"));
208 : 0 : buf.append(executable);
209 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -e -p "));
210 : 0 : buf.append(project);
211 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -r "));
212 : 0 : buf.append(projectRoot);
213 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -i "));
214 : 0 : buf.append(inPath);
215 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -o "));
216 : 0 : buf.append(outPath);
217 : 0 : buf.appendAscii(RTL_CONSTASCII_STRINGPARAM(" -l en-US"));
218 : 0 : rtl::OString cmd;
219 : 0 : if (!buf.makeStringAndClear().convertToString(
220 : 0 : &cmd, osl_getThreadTextEncoding(),
221 : : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
222 : 0 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
223 : : {
224 : 0 : std::cerr << "Error: Cannot convert command from UTF-16\n";
225 : 0 : throw false; //TODO
226 : : }
227 : 0 : if (system(cmd.getStr()) != 0) {
228 : 0 : std::cerr << "Error: Failed to execute " << cmd.getStr() << '\n';
229 : 0 : throw false; //TODO
230 : : }
231 : 0 : rtl::OString outPath8;
232 : 0 : if (!outPath.convertToString(
233 : 0 : &outPath8, osl_getThreadTextEncoding(),
234 : : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
235 : 0 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
236 : : {
237 : 0 : std::cerr << "Error: Cannot convert pathname from UTF-16\n";
238 : 0 : throw false; //TODO
239 : : }
240 : 0 : std::ifstream in(outPath8.getStr());
241 : 0 : if (!in.is_open()) {
242 : 0 : std::cerr << "Error: Cannot open " << outPath.getStr() << "\n";
243 : 0 : throw false; //TODO
244 : : }
245 : 0 : while (!in.eof())
246 : : {
247 : 0 : std::string s;
248 : 0 : std::getline(in, s);
249 : 0 : if (!s.empty())
250 : 0 : global::output << s << '\n';
251 : 0 : }
252 : 0 : in.close();
253 : : }
254 : 0 : }
255 : :
256 : 0 : void handleFile(
257 : : rtl::OUString const & project, rtl::OUString const & projectRoot,
258 : : rtl::OUString const & url)
259 : : {
260 : : struct Command {
261 : : char const * extension;
262 : : sal_Int32 extensionLength;
263 : : char const * executable;
264 : : bool positive;
265 : : };
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 : 0 : for (std::size_t i = 0; i != SAL_N_ELEMENTS(commands); ++i) {
276 : 0 : if (url.endsWithAsciiL(
277 : 0 : commands[i].extension, commands[i].extensionLength))
278 : : {
279 : : handleCommand(
280 : : project, projectRoot, url,
281 : : rtl::OUString::createFromAscii(commands[i].executable),
282 : 0 : commands[i].positive);
283 : 0 : break;
284 : : }
285 : : }
286 : 0 : }
287 : :
288 : 0 : bool includeProject(rtl::OUString const & project) {
289 : : static char const * projects[] = {
290 : : "accessibility",
291 : : "avmedia",
292 : : "basctl",
293 : : "basic",
294 : : "chart2",
295 : : "connectivity",
296 : : "cui",
297 : : "dbaccess",
298 : : "desktop",
299 : : "dictionaries",
300 : : "editeng",
301 : : "extensions",
302 : : "filter",
303 : : "forms",
304 : : "formula",
305 : : "fpicker",
306 : : "framework",
307 : : "helpcontent2",
308 : : "instsetoo_native",
309 : : "mysqlc",
310 : : "nlpsolver",
311 : : "officecfg",
312 : : "padmin",
313 : : "readlicense_oo",
314 : : "reportbuilder",
315 : : "reportdesign",
316 : : "sc",
317 : : "scaddins",
318 : : "sccomp",
319 : : "scp2",
320 : : "scripting",
321 : : "sd",
322 : : "sdext",
323 : : "setup_native",
324 : : "sfx2",
325 : : "shell",
326 : : "starmath",
327 : : "svl",
328 : : "svtools",
329 : : "svx",
330 : : "sw",
331 : : "swext",
332 : : "sysui",
333 : : "uui",
334 : : "vcl",
335 : : "wizards",
336 : : "xmlsecurity" };
337 : 0 : for (std::size_t i = 0; i != SAL_N_ELEMENTS(projects); ++i) {
338 : 0 : if (project.equalsAscii(projects[i])) {
339 : 0 : return true;
340 : : }
341 : : }
342 : 0 : return false;
343 : : }
344 : :
345 : 0 : 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 : 0 : for (std::size_t i = 0; i != SAL_N_ELEMENTS(excluded); ++i) {
364 : 0 : if (directory.matchAsciiL(excluded[i].string, excluded[i].length)) {
365 : 0 : return true;
366 : : }
367 : : }
368 : 0 : return false;
369 : : }
370 : :
371 : : /// Handle one directory in the hierarchy.
372 : : ///
373 : : /// Ignores symlinks and instead explicitly descends into clone/* or src/*,
374 : : /// as the Cygwin symlinks are not supported by osl::Directory on Windows.
375 : : ///
376 : : /// @param url the absolute file URL of this directory
377 : : ///
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
382 : : ///
383 : : /// @param project the name of the project (empty and ignored if level <= 0)
384 : : ///
385 : : /// @param the relative path back to the project root (empty and ignored if
386 : : /// level <= 0)
387 : 0 : void handleDirectory(
388 : : rtl::OUString const & url, int level, rtl::OUString const & project,
389 : : rtl::OUString const & projectRoot)
390 : : {
391 : 0 : osl::Directory dir(url);
392 : 0 : if (dir.open() != osl::FileBase::E_None) {
393 : : std::cerr
394 : 0 : << "Error: Cannot open directory: "
395 : 0 : << rtl::OUStringToOString(url, osl_getThreadTextEncoding()).getStr()
396 : 0 : << '\n';
397 : 0 : throw false; //TODO
398 : : }
399 : 0 : for (;;) {
400 : 0 : osl::DirectoryItem item;
401 : 0 : osl::FileBase::RC e = dir.getNextItem(item);
402 : 0 : if (e == osl::FileBase::E_NOENT) {
403 : : break;
404 : : }
405 : 0 : if (e != osl::FileBase::E_None) {
406 : 0 : std::cerr << "Error: Cannot read directory\n";
407 : 0 : throw false; //TODO
408 : : }
409 : : osl::FileStatus stat(
410 : : osl_FileStatus_Mask_Type | osl_FileStatus_Mask_FileName
411 : 0 : | osl_FileStatus_Mask_FileURL);
412 : 0 : if (item.getFileStatus(stat) != osl::FileBase::E_None) {
413 : 0 : std::cerr << "Error: Cannot get file status\n";
414 : 0 : throw false; //TODO
415 : : }
416 : 0 : switch (level) {
417 : : case -1: // the clone or src directory
418 : 0 : if (stat.getFileType() == osl::FileStatus::Directory) {
419 : : handleDirectory(
420 : 0 : stat.getFileURL(), 0, rtl::OUString(), rtl::OUString());
421 : : }
422 : 0 : break;
423 : : case 0: // a root directory
424 : 0 : if (stat.getFileType() == osl::FileStatus::Directory) {
425 : 0 : if (includeProject(stat.getFileName())) {
426 : : handleDirectory(
427 : : stat.getFileURL(), 1, stat.getFileName(),
428 : 0 : rtl::OUString());
429 : 0 : } else if ( stat.getFileName() == "clone" || stat.getFileName() == "src" )
430 : : {
431 : : handleDirectory(
432 : : stat.getFileURL(), -1, rtl::OUString(),
433 : 0 : rtl::OUString());
434 : : }
435 : : }
436 : 0 : break;
437 : : default:
438 : 0 : if (stat.getFileType() == osl::FileStatus::Directory) {
439 : 0 : if (level == 2 || !excludeDirectory(stat.getFileName())) {
440 : 0 : rtl::OUString pr(projectRoot);
441 : 0 : if (!pr.isEmpty()) {
442 : 0 : pr += rtl::OUString('/');
443 : : }
444 : 0 : pr += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".."));
445 : 0 : handleDirectory(stat.getFileURL(), 2, project, pr);
446 : : }
447 : : } else {
448 : 0 : handleFile(project, projectRoot, stat.getFileURL());
449 : : }
450 : 0 : break;
451 : : }
452 : 0 : }
453 : 0 : if (dir.close() != osl::FileBase::E_None) {
454 : 0 : std::cerr << "Error: Cannot close directory\n";
455 : 0 : throw false; //TODO
456 : 0 : }
457 : 0 : }
458 : :
459 : 0 : void handleProjects(char const * root) {
460 : 0 : rtl::OUString root16;
461 : 0 : if (!rtl_convertStringToUString(
462 : : &root16.pData, root, rtl_str_getLength(root),
463 : 0 : osl_getThreadTextEncoding(),
464 : : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
465 : : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
466 : 0 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
467 : : {
468 : 0 : std::cerr << "Error: Cannot convert pathname to UTF-16\n";
469 : 0 : throw false; //TODO
470 : : }
471 : 0 : rtl::OUString rootUrl;
472 : 0 : if (osl::FileBase::getFileURLFromSystemPath(root16, rootUrl)
473 : : != osl::FileBase::E_None)
474 : : {
475 : 0 : std::cerr << "Error: Cannot convert pathname to URL\n";
476 : 0 : throw false; //TODO
477 : : }
478 : 0 : handleDirectory(rootUrl, 0, rtl::OUString(), rtl::OUString());
479 : 0 : }
480 : :
481 : : }
482 : :
483 : 0 : SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) {
484 : 0 : if (argc != 3) {
485 : : std::cerr
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 : 0 : "Syntax: localize <source-root> <outfile>\n");
491 : 0 : std::exit(EXIT_FAILURE);
492 : : }
493 : 0 : global::output.open(argv[2], std::ios_base::out | std::ios_base::trunc);
494 : 0 : if (!global::output.is_open()) {
495 : 0 : std::cerr << "Error: Cannot append to " << argv[2] << '\n';
496 : 0 : std::exit(EXIT_FAILURE);
497 : : }
498 : : try {
499 : 0 : handleProjects(argv[1]);
500 : 0 : } catch (bool) { //TODO
501 : 0 : return EXIT_FAILURE;
502 : : }
503 : 0 : global::output.close();
504 : 0 : return EXIT_SUCCESS;
505 : 0 : }
506 : :
507 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|