Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "sal/config.h"
11 :
12 : #include <cassert>
13 : #include <cstddef>
14 : #include <cstdlib>
15 : #include <iostream>
16 : #include <map>
17 : #include <utility>
18 : #include <vector>
19 :
20 : #include "config_version.h"
21 : #include "osl/endian.h"
22 : #include "osl/file.h"
23 : #include "osl/file.hxx"
24 : #include "osl/process.h"
25 : #include "rtl/process.h"
26 : #include "rtl/string.h"
27 : #include "rtl/string.hxx"
28 : #include "rtl/textenc.h"
29 : #include "rtl/textcvt.h"
30 : #include "rtl/ustring.hxx"
31 : #include "sal/macros.h"
32 : #include "sal/main.h"
33 : #include "unoidl/unoidl.hxx"
34 :
35 : namespace {
36 :
37 25 : OUString getArgumentUri(sal_uInt32 argument) {
38 25 : OUString arg;
39 25 : rtl_getAppCommandArg(argument, &arg.pData);
40 50 : OUString url;
41 25 : osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
42 25 : if (e1 != osl::FileBase::E_None) {
43 : std::cerr
44 0 : << "Cannot convert \"" << arg << "\" to file URL, error code "
45 0 : << +e1 << std::endl;
46 0 : std::exit(EXIT_FAILURE);
47 : }
48 50 : OUString cwd;
49 25 : oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
50 25 : if (e2 != osl_Process_E_None) {
51 : std::cerr
52 0 : << "Cannot obtain working directory, error code " << +e2
53 0 : << std::endl;
54 0 : std::exit(EXIT_FAILURE);
55 : }
56 25 : OUString abs;
57 25 : e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
58 25 : if (e1 != osl::FileBase::E_None) {
59 : std::cerr
60 0 : << "Cannot make \"" << url
61 0 : << "\" into an absolute file URL, error code " << +e1 << std::endl;
62 0 : std::exit(EXIT_FAILURE);
63 : }
64 50 : return abs;
65 : }
66 :
67 17 : rtl::Reference< unoidl::Provider > load(
68 : rtl::Reference< unoidl::Manager > const & manager, OUString const & uri)
69 : {
70 : try {
71 17 : return unoidl::loadProvider(manager, uri);
72 0 : } catch (unoidl::NoSuchFileException &) {
73 0 : std::cerr << "Input <" << uri << "> does not exist" << std::endl;
74 0 : std::exit(EXIT_FAILURE);
75 0 : } catch (unoidl::FileFormatException & e) {
76 : std::cerr
77 0 : << "Cannot read input <" << uri << ">: " << e.getDetail()
78 0 : << std::endl;
79 0 : std::exit(EXIT_FAILURE);
80 : }
81 : }
82 :
83 50362 : sal_uInt64 getOffset(osl::File & file) {
84 : sal_uInt64 off;
85 50362 : osl::FileBase::RC e = file.getPos(off);
86 50362 : if (e != osl::FileBase::E_None) {
87 : std::cerr
88 0 : << "Cannot determine current position in <" << file.getURL()
89 0 : << ">, error code " << +e << std::endl;
90 0 : std::exit(EXIT_FAILURE);
91 : }
92 50362 : return off;
93 : }
94 :
95 193009 : void write(osl::File & file, void const * buffer, sal_uInt64 size) {
96 : sal_uInt64 n;
97 193009 : osl::FileBase::RC e = file.write(buffer, size, n);
98 193009 : if (e != osl::FileBase::E_None) {
99 : std::cerr
100 0 : << "Cannot write to <" << file.getURL() << ">, error code " << +e
101 0 : << std::endl;
102 0 : std::exit(EXIT_FAILURE);
103 : }
104 193009 : if (n != size) {
105 : std::cerr
106 0 : << "Bad write of " << n << " instead of " << size << " bytes to <"
107 0 : << file.getURL() << '>' << std::endl;
108 0 : std::exit(EXIT_FAILURE);
109 : }
110 193009 : }
111 :
112 26651 : void write8(osl::File & file, sal_uInt64 value) {
113 26651 : if (value > 0xFF) {
114 : std::cerr
115 0 : << "Cannot write value >= 2^8; input is too large" << std::endl;
116 0 : std::exit(EXIT_FAILURE);
117 : }
118 : unsigned char buf[1];
119 26651 : buf[0] = value & 0xFF;
120 26651 : write(file, buf, SAL_N_ELEMENTS(buf));
121 26651 : }
122 :
123 5150 : void write16(osl::File & file, sal_uInt64 value) {
124 5150 : if (value > 0xFFFF) {
125 : std::cerr
126 0 : << "Cannot write value >= 2^16; input is too large" << std::endl;
127 0 : std::exit(EXIT_FAILURE);
128 : }
129 : unsigned char buf[2];
130 5150 : buf[0] = value & 0xFF;
131 5150 : buf[1] = (value >> 8) & 0xFF;
132 5150 : write(file, buf, SAL_N_ELEMENTS(buf));
133 5150 : }
134 :
135 128453 : void write32(osl::File & file, sal_uInt64 value) {
136 128453 : if (value > 0xFFFFFFFF) {
137 : std::cerr
138 0 : << "Cannot write value >= 2^32; input is too large" << std::endl;
139 0 : std::exit(EXIT_FAILURE);
140 : }
141 : unsigned char buf[4];
142 128453 : buf[0] = value & 0xFF;
143 128453 : buf[1] = (value >> 8) & 0xFF;
144 128453 : buf[2] = (value >> 16) & 0xFF;
145 128453 : buf[3] = (value >> 24) & 0xFF;
146 128453 : write(file, buf, SAL_N_ELEMENTS(buf));
147 128453 : }
148 :
149 33 : void write64(osl::File & file, sal_uInt64 value) {
150 : unsigned char buf[8];
151 33 : buf[0] = value & 0xFF;
152 33 : buf[1] = (value >> 8) & 0xFF;
153 33 : buf[2] = (value >> 16) & 0xFF;
154 33 : buf[3] = (value >> 24) & 0xFF;
155 33 : buf[4] = (value >> 32) & 0xFF;
156 33 : buf[5] = (value >> 40) & 0xFF;
157 33 : buf[6] = (value >> 48) & 0xFF;
158 33 : buf[7] = (value >> 56) & 0xFF;
159 33 : write(file, buf, SAL_N_ELEMENTS(buf));
160 33 : }
161 :
162 20 : void writeIso60599Binary32(osl::File & file, float value) {
163 : union {
164 : unsigned char buf[4];
165 : float f; // assuming float is ISO 60599 binary32
166 : } sa;
167 20 : sa.f = value;
168 : #if defined OSL_BIGENDIAN
169 : std::swap(sa.buf[0], sa.buf[3]);
170 : std::swap(sa.buf[1], sa.buf[2]);
171 : #endif
172 20 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
173 20 : }
174 :
175 0 : void writeIso60599Binary64(osl::File & file, double value) {
176 : union {
177 : unsigned char buf[8];
178 : float d; // assuming double is ISO 60599 binary64
179 : } sa;
180 0 : sa.d = value;
181 : #if defined OSL_BIGENDIAN
182 : std::swap(sa.buf[0], sa.buf[7]);
183 : std::swap(sa.buf[1], sa.buf[6]);
184 : std::swap(sa.buf[2], sa.buf[5]);
185 : std::swap(sa.buf[3], sa.buf[4]);
186 : #endif
187 0 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
188 0 : }
189 :
190 67885 : OString toAscii(OUString const & name) {
191 67885 : OString ascii;
192 67885 : if (!name.convertToString(
193 : &ascii, RTL_TEXTENCODING_ASCII_US,
194 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
195 67885 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
196 : {
197 : std::cerr
198 0 : << "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
199 0 : std::exit(EXIT_FAILURE);
200 : }
201 67885 : return ascii;
202 : }
203 :
204 260 : OString toUtf8(OUString const & string) {
205 260 : OString ascii;
206 260 : if (!string.convertToString(
207 : &ascii, RTL_TEXTENCODING_UTF8,
208 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
209 260 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
210 : {
211 : std::cerr
212 0 : << "Cannot convert \"" << string << "\" to UTF-8" << std::endl;
213 0 : std::exit(EXIT_FAILURE);
214 : }
215 260 : return ascii;
216 : }
217 :
218 17660 : sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
219 17660 : OString ascii(toAscii(name));
220 17660 : if (ascii.indexOf('\0') != -1) {
221 : std::cerr
222 0 : << "Name \"" << ascii << "\" contains NUL characters" << std::endl;
223 0 : std::exit(EXIT_FAILURE);
224 : }
225 17660 : sal_uInt64 off = getOffset(file);
226 17660 : write(file, ascii.getStr(), ascii.getLength() + 1);
227 17660 : return off;
228 : }
229 :
230 50485 : void writeIdxString(osl::File & file, OString const & string) {
231 50485 : static std::map< OString, sal_uInt64 > reuse;
232 50485 : std::map< OString, sal_uInt64 >::iterator i(reuse.find(string));
233 50485 : if (i == reuse.end()) {
234 15026 : reuse.insert(std::make_pair(string, getOffset(file)));
235 : assert(
236 : (static_cast< sal_uInt64 >(string.getLength()) & 0x80000000) == 0);
237 15026 : write32(file, static_cast< sal_uInt64 >(string.getLength()));
238 15026 : write(file, string.getStr(), string.getLength());
239 : } else {
240 35459 : if ((i->second & 0x80000000) != 0) {
241 : std::cerr
242 0 : << "Cannot write index 0x" << std::hex << i->second << std::dec
243 0 : << " of \"" << string << "\"; input is too large" << std::endl;
244 0 : std::exit(EXIT_FAILURE);
245 : }
246 35459 : write32(file, i->second | 0x80000000);
247 : }
248 50485 : }
249 :
250 50225 : void writeIdxName(osl::File & file, OUString const & name) {
251 50225 : writeIdxString(file, toAscii(name));
252 50225 : }
253 :
254 36130 : void writeAnnotations(
255 : osl::File & file, bool annotate,
256 : std::vector< OUString > const & annotations)
257 : {
258 : assert(annotate || annotations.empty());
259 36130 : if (annotate) {
260 1309 : write32(file, annotations.size());
261 : // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
262 4707 : for (std::vector< OUString >::const_iterator i(annotations.begin());
263 3138 : i != annotations.end(); ++i)
264 : {
265 260 : writeIdxString(file, toUtf8(*i));
266 : }
267 : }
268 36130 : }
269 :
270 5685 : void writeKind(
271 : osl::File & file,
272 : rtl::Reference< unoidl::PublishableEntity > const & entity,
273 : bool annotated, bool flag = false)
274 : {
275 : assert(entity.is());
276 5685 : sal_uInt64 v = entity->getSort();
277 5685 : if (entity->isPublished()) {
278 2691 : v |= 0x80;
279 : }
280 5685 : if (annotated) {
281 212 : v |= 0x40;
282 : }
283 5685 : if (flag) {
284 585 : v |= 0x20;
285 : }
286 5685 : write8(file, v);
287 5685 : }
288 :
289 29290 : struct Item {
290 5858 : explicit Item(rtl::Reference< unoidl::Entity > const & theEntity):
291 5858 : entity(theEntity), nameOffset(0), dataOffset(0)
292 5858 : {}
293 :
294 : rtl::Reference< unoidl::Entity > entity;
295 : sal_uInt64 nameOffset;
296 : sal_uInt64 dataOffset;
297 : };
298 :
299 59010 : struct ConstItem {
300 11802 : ConstItem(
301 : unoidl::ConstantValue const & theConstant,
302 : std::vector< OUString > const & theAnnotations):
303 : constant(theConstant), annotations(theAnnotations), nameOffset(0),
304 11802 : dataOffset(0)
305 11802 : {}
306 :
307 : unoidl::ConstantValue constant;
308 : std::vector< OUString > annotations;
309 : sal_uInt64 nameOffset;
310 : sal_uInt64 dataOffset;
311 : };
312 :
313 181 : sal_uInt64 writeMap(
314 : osl::File & file, rtl::Reference< unoidl::MapCursor > const & cursor,
315 : std::size_t * rootSize)
316 : {
317 : assert(cursor.is());
318 181 : std::map< OUString, Item > map;
319 : for (;;) {
320 6039 : OUString name;
321 11897 : rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
322 6039 : if (!ent.is()) {
323 181 : break;
324 : }
325 5858 : if (!map.insert(std::make_pair(name, Item(ent))).second) {
326 0 : std::cout << "Duplicate name \"" << name << '"' << std::endl;
327 0 : std::exit(EXIT_FAILURE);
328 : }
329 5858 : }
330 6039 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
331 : ++i)
332 : {
333 5858 : switch (i->second.entity->getSort()) {
334 : case unoidl::Entity::SORT_MODULE:
335 : {
336 : rtl::Reference< unoidl::ModuleEntity > ent2(
337 : static_cast< unoidl::ModuleEntity * >(
338 173 : i->second.entity.get()));
339 173 : i->second.dataOffset = writeMap(file, ent2->createCursor(), 0);
340 173 : break;
341 : }
342 : case unoidl::Entity::SORT_ENUM_TYPE:
343 : {
344 : rtl::Reference< unoidl::EnumTypeEntity > ent2(
345 : static_cast< unoidl::EnumTypeEntity * >(
346 196 : i->second.entity.get()));
347 196 : bool ann = !ent2->getAnnotations().empty();
348 4416 : for (std::vector< unoidl::EnumTypeEntity::Member >::
349 196 : const_iterator j(ent2->getMembers().begin());
350 4386 : !ann && j != ent2->getMembers().end(); ++j)
351 : {
352 1271 : ann = !j->annotations.empty();
353 : }
354 196 : i->second.dataOffset = getOffset(file);
355 196 : writeKind(file, ent2.get(), ann);
356 196 : write32(file, ent2->getMembers().size());
357 4548 : for (std::vector< unoidl::EnumTypeEntity::Member >::
358 196 : const_iterator j(ent2->getMembers().begin());
359 3032 : j != ent2->getMembers().end(); ++j)
360 : {
361 1320 : writeIdxName(file, j->name);
362 1320 : write32(file, static_cast< sal_uInt32 >(j->value));
363 1320 : writeAnnotations(file, ann, j->annotations);
364 : }
365 196 : writeAnnotations(file, ann, ent2->getAnnotations());
366 196 : break;
367 : }
368 : case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
369 : {
370 : rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
371 : static_cast< unoidl::PlainStructTypeEntity * >(
372 407 : i->second.entity.get()));
373 407 : bool ann = !ent2->getAnnotations().empty();
374 5430 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
375 407 : const_iterator j(ent2->getDirectMembers().begin());
376 5400 : !ann && j != ent2->getDirectMembers().end(); ++j)
377 : {
378 1398 : ann = !j->annotations.empty();
379 : }
380 407 : i->second.dataOffset = getOffset(file);
381 : writeKind(
382 407 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
383 407 : if (!ent2->getDirectBase().isEmpty()) {
384 103 : writeIdxName(file, ent2->getDirectBase());
385 : }
386 407 : write32(file, ent2->getDirectMembers().size());
387 5580 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
388 407 : const_iterator j(ent2->getDirectMembers().begin());
389 3720 : j != ent2->getDirectMembers().end(); ++j)
390 : {
391 1453 : writeIdxName(file, j->name);
392 1453 : writeIdxName(file, j->type);
393 1453 : writeAnnotations(file, ann, j->annotations);
394 : }
395 407 : writeAnnotations(file, ann, ent2->getAnnotations());
396 407 : break;
397 : }
398 : case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
399 : {
400 : rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity >
401 : ent2(
402 : static_cast<
403 : unoidl::PolymorphicStructTypeTemplateEntity * >(
404 8 : i->second.entity.get()));
405 8 : bool ann = !ent2->getAnnotations().empty();
406 66 : for (std::vector<
407 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
408 : const_iterator j(
409 8 : ent2->getMembers().begin());
410 66 : !ann && j != ent2->getMembers().end(); ++j)
411 : {
412 14 : ann = !j->annotations.empty();
413 : }
414 8 : i->second.dataOffset = getOffset(file);
415 8 : writeKind(file, ent2.get(), ann);
416 8 : write32(file, ent2->getTypeParameters().size());
417 57 : for (std::vector< OUString >::const_iterator j(
418 8 : ent2->getTypeParameters().begin());
419 38 : j != ent2->getTypeParameters().end(); ++j)
420 : {
421 11 : writeIdxName(file, *j);
422 : }
423 8 : write32(file, ent2->getMembers().size());
424 66 : for (std::vector<
425 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
426 : const_iterator j(
427 8 : ent2->getMembers().begin());
428 44 : j != ent2->getMembers().end(); ++j)
429 : {
430 14 : sal_uInt64 f = 0;
431 14 : if (j->parameterized) {
432 9 : f |= 0x01;
433 : }
434 14 : write8(file, f);
435 14 : writeIdxName(file, j->name);
436 14 : writeIdxName(file, j->type);
437 14 : writeAnnotations(file, ann, j->annotations);
438 : }
439 8 : writeAnnotations(file, ann, ent2->getAnnotations());
440 8 : break;
441 : }
442 : case unoidl::Entity::SORT_EXCEPTION_TYPE:
443 : {
444 : rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
445 : static_cast< unoidl::ExceptionTypeEntity * >(
446 250 : i->second.entity.get()));
447 250 : bool ann = !ent2->getAnnotations().empty();
448 1229 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
449 250 : const_iterator j(ent2->getDirectMembers().begin());
450 1225 : !ann && j != ent2->getDirectMembers().end(); ++j)
451 : {
452 159 : ann = !j->annotations.empty();
453 : }
454 250 : i->second.dataOffset = getOffset(file);
455 : writeKind(
456 250 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
457 250 : if (!ent2->getDirectBase().isEmpty()) {
458 249 : writeIdxName(file, ent2->getDirectBase());
459 : }
460 250 : write32(file, ent2->getDirectMembers().size());
461 1230 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
462 250 : const_iterator j(ent2->getDirectMembers().begin());
463 820 : j != ent2->getDirectMembers().end(); ++j)
464 : {
465 160 : writeIdxName(file, j->name);
466 160 : writeIdxName(file, j->type);
467 160 : writeAnnotations(file, ann, j->annotations);
468 : }
469 250 : writeAnnotations(file, ann, ent2->getAnnotations());
470 250 : break;
471 : }
472 : case unoidl::Entity::SORT_INTERFACE_TYPE:
473 : {
474 : rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
475 : static_cast< unoidl::InterfaceTypeEntity * >(
476 1901 : i->second.entity.get()));
477 1901 : bool ann = !ent2->getAnnotations().empty();
478 11956 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
479 1901 : j(ent2->getDirectMandatoryBases().begin());
480 11762 : !ann && j != ent2->getDirectMandatoryBases().end(); ++j)
481 : {
482 2052 : ann = !j->annotations.empty();
483 : }
484 5827 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
485 1901 : j(ent2->getDirectOptionalBases().begin());
486 5633 : !ann && j != ent2->getDirectOptionalBases().end(); ++j)
487 : {
488 9 : ann = !j->annotations.empty();
489 : }
490 9371 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
491 1901 : const_iterator j(ent2->getDirectAttributes().begin());
492 9175 : !ann && j != ent2->getDirectAttributes().end(); ++j)
493 : {
494 1190 : ann = !j->annotations.empty();
495 : }
496 23734 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
497 1901 : const_iterator j(ent2->getDirectMethods().begin());
498 23528 : !ann && j != ent2->getDirectMethods().end(); ++j)
499 : {
500 5976 : ann = !j->annotations.empty();
501 : }
502 1901 : i->second.dataOffset = getOffset(file);
503 1901 : writeKind(file, ent2.get(), ann);
504 1901 : write32(file, ent2->getDirectMandatoryBases().size());
505 12153 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
506 1901 : j(ent2->getDirectMandatoryBases().begin());
507 8102 : j != ent2->getDirectMandatoryBases().end(); ++j)
508 : {
509 2150 : writeIdxName(file, j->name);
510 2150 : writeAnnotations(file, ann, j->annotations);
511 : }
512 1901 : write32(file, ent2->getDirectOptionalBases().size());
513 5730 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
514 1901 : j(ent2->getDirectOptionalBases().begin());
515 3820 : j != ent2->getDirectOptionalBases().end(); ++j)
516 : {
517 9 : writeIdxName(file, j->name);
518 9 : writeAnnotations(file, ann, j->annotations);
519 : }
520 1901 : write32(file, ent2->getDirectAttributes().size());
521 9288 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
522 1901 : const_iterator j(ent2->getDirectAttributes().begin());
523 6192 : j != ent2->getDirectAttributes().end(); ++j)
524 : {
525 1195 : sal_uInt64 f = 0;
526 1195 : if (j->bound) {
527 153 : f |= 0x01;
528 : }
529 1195 : if (j->readOnly) {
530 269 : f |= 0x02;
531 : }
532 1195 : write8(file, f);
533 1195 : writeIdxName(file, j->name);
534 1195 : writeIdxName(file, j->type);
535 1195 : write32(file, j->getExceptions.size());
536 3846 : for (std::vector< OUString >::const_iterator k(
537 1195 : j->getExceptions.begin());
538 2564 : k != j->getExceptions.end(); ++k)
539 : {
540 87 : writeIdxName(file, *k);
541 : }
542 1195 : if (!j->readOnly) {
543 926 : write32(file, j->setExceptions.size());
544 3135 : for (std::vector< OUString >::const_iterator k(
545 926 : j->setExceptions.begin());
546 2090 : k != j->setExceptions.end(); ++k)
547 : {
548 119 : writeIdxName(file, *k);
549 : }
550 : }
551 1195 : writeAnnotations(file, ann, j->annotations);
552 : }
553 1901 : write32(file, ent2->getDirectMethods().size());
554 24624 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
555 1901 : const_iterator j(ent2->getDirectMethods().begin());
556 16416 : j != ent2->getDirectMethods().end(); ++j)
557 : {
558 6307 : writeIdxName(file, j->name);
559 6307 : writeIdxName(file, j->returnType);
560 6307 : write32(file, j->parameters.size());
561 40029 : for (std::vector<
562 : unoidl::InterfaceTypeEntity::Method::Parameter >::
563 6307 : const_iterator k(j->parameters.begin());
564 26686 : k != j->parameters.end(); ++k)
565 : {
566 7036 : write8(file, k->direction);
567 7036 : writeIdxName(file, k->name);
568 7036 : writeIdxName(file, k->type);
569 : }
570 6307 : write32(file, j->exceptions.size());
571 27744 : for (std::vector< OUString >::const_iterator k(
572 6307 : j->exceptions.begin());
573 18496 : k != j->exceptions.end(); ++k)
574 : {
575 2941 : writeIdxName(file, *k);
576 : }
577 6307 : writeAnnotations(file, ann, j->annotations);
578 : }
579 1901 : writeAnnotations(file, ann, ent2->getAnnotations());
580 1901 : break;
581 : }
582 : case unoidl::Entity::SORT_TYPEDEF:
583 : {
584 : rtl::Reference< unoidl::TypedefEntity > ent2(
585 : static_cast< unoidl::TypedefEntity * >(
586 56 : i->second.entity.get()));
587 56 : bool ann = !ent2->getAnnotations().empty();
588 56 : i->second.dataOffset = getOffset(file);
589 56 : writeKind(file, ent2.get(), ann);
590 56 : writeIdxName(file, ent2->getType());
591 56 : writeAnnotations(file, ann, ent2->getAnnotations());
592 56 : break;
593 : }
594 : case unoidl::Entity::SORT_CONSTANT_GROUP:
595 : {
596 : rtl::Reference< unoidl::ConstantGroupEntity > ent2(
597 : static_cast< unoidl::ConstantGroupEntity * >(
598 1182 : i->second.entity.get()));
599 2364 : std::map< OUString, ConstItem > cmap;
600 38952 : for (std::vector< unoidl::ConstantGroupEntity::Member >::
601 1182 : const_iterator j(ent2->getMembers().begin());
602 25968 : j != ent2->getMembers().end(); ++j)
603 : {
604 23604 : if (!cmap.insert(
605 : std::make_pair(
606 23604 : j->name, ConstItem(j->value, j->annotations))).
607 23604 : second)
608 : {
609 : std::cout
610 0 : << "Duplicate constant group member name \""
611 0 : << j->name << '"' << std::endl;
612 0 : std::exit(EXIT_FAILURE);
613 : }
614 : }
615 38952 : for (std::map< OUString, ConstItem >::iterator j(cmap.begin());
616 25968 : j != cmap.end(); ++j)
617 : {
618 11802 : j->second.dataOffset = getOffset(file);
619 11802 : sal_uInt64 v = j->second.constant.type;
620 11802 : if (!j->second.annotations.empty()) {
621 14 : v |= 0x80;
622 : }
623 11802 : write8(file, v);
624 11802 : switch (j->second.constant.type) {
625 : case unoidl::ConstantValue::TYPE_BOOLEAN:
626 0 : write8(file, j->second.constant.booleanValue ? 1 : 0);
627 0 : break;
628 : case unoidl::ConstantValue::TYPE_BYTE:
629 : write8(
630 : file,
631 : static_cast< sal_uInt8 >(
632 248 : j->second.constant.byteValue));
633 248 : break;
634 : case unoidl::ConstantValue::TYPE_SHORT:
635 : write16(
636 : file,
637 : static_cast< sal_uInt16 >(
638 2046 : j->second.constant.shortValue));
639 2046 : break;
640 : case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
641 2 : write16(file, j->second.constant.unsignedShortValue);
642 2 : break;
643 : case unoidl::ConstantValue::TYPE_LONG:
644 : write32(
645 : file,
646 : static_cast< sal_uInt32 >(
647 9451 : j->second.constant.longValue));
648 9451 : break;
649 : case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
650 2 : write32(file, j->second.constant.unsignedLongValue);
651 2 : break;
652 : case unoidl::ConstantValue::TYPE_HYPER:
653 : write64(
654 : file,
655 : static_cast< sal_uInt64 >(
656 31 : j->second.constant.hyperValue));
657 31 : break;
658 : case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
659 2 : write64(file, j->second.constant.unsignedHyperValue);
660 2 : break;
661 : case unoidl::ConstantValue::TYPE_FLOAT:
662 : writeIso60599Binary32(
663 20 : file, j->second.constant.floatValue);
664 20 : break;
665 : case unoidl::ConstantValue::TYPE_DOUBLE:
666 : writeIso60599Binary64(
667 0 : file, j->second.constant.doubleValue);
668 0 : break;
669 : default:
670 0 : for (;;) { std::abort(); } // this cannot happen
671 : }
672 : writeAnnotations(
673 11802 : file, !j->second.annotations.empty(),
674 23604 : j->second.annotations);
675 : }
676 38952 : for (std::map< OUString, ConstItem >::iterator j(
677 1182 : cmap.begin());
678 25968 : j != cmap.end(); ++j)
679 : {
680 11802 : j->second.nameOffset = writeNulName(file, j->first);
681 : }
682 1182 : bool ann = !ent2->getAnnotations().empty();
683 1182 : i->second.dataOffset = getOffset(file);
684 1182 : writeKind(file, ent2.get(), ann);
685 1182 : write32(file, cmap.size());
686 : // overflow from std::map::size_type -> sal_uInt64 is
687 : // unrealistic
688 38952 : for (std::map< OUString, ConstItem >::iterator j(
689 1182 : cmap.begin());
690 25968 : j != cmap.end(); ++j)
691 : {
692 11802 : write32(file, j->second.nameOffset);
693 11802 : write32(file, j->second.dataOffset);
694 : }
695 1182 : writeAnnotations(file, ann, ent2->getAnnotations());
696 2364 : break;
697 : }
698 : case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
699 : {
700 : rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
701 : ent2(
702 : static_cast<
703 : unoidl::SingleInterfaceBasedServiceEntity * >(
704 493 : i->second.entity.get()));
705 493 : bool dfltCtor = ent2->getConstructors().size() == 1
706 493 : && ent2->getConstructors()[0].defaultConstructor;
707 493 : bool ann = !ent2->getAnnotations().empty();
708 493 : if (!dfltCtor) {
709 1644 : for (std::vector<
710 : unoidl::SingleInterfaceBasedServiceEntity::
711 : Constructor >::const_iterator j(
712 260 : ent2->getConstructors().begin());
713 1644 : !ann && j != ent2->getConstructors().end(); ++j)
714 : {
715 288 : ann = !j->annotations.empty();
716 : }
717 : }
718 493 : i->second.dataOffset = getOffset(file);
719 493 : writeKind(file, ent2.get(), ann, dfltCtor);
720 493 : writeIdxName(file, ent2->getBase());
721 493 : if (!dfltCtor) {
722 260 : write32(file, ent2->getConstructors().size());
723 1644 : for (std::vector<
724 : unoidl::SingleInterfaceBasedServiceEntity::
725 : Constructor >::const_iterator j(
726 260 : ent2->getConstructors().begin());
727 1096 : j != ent2->getConstructors().end(); ++j)
728 : {
729 288 : if (j->defaultConstructor) {
730 : std::cout
731 0 : << "Unexpected default constructor \""
732 0 : << j->name << '"' << std::endl;
733 0 : std::exit(EXIT_FAILURE);
734 : }
735 288 : writeIdxName(file, j->name);
736 288 : write32(file, j->parameters.size());
737 2358 : for (std::vector<
738 : unoidl::SingleInterfaceBasedServiceEntity::
739 : Constructor::Parameter >::const_iterator k(
740 288 : j->parameters.begin());
741 1572 : k != j->parameters.end(); ++k)
742 : {
743 498 : sal_uInt64 f = 0;
744 498 : if (k->rest) {
745 2 : f |= 0x04;
746 : }
747 498 : write8(file, f);
748 498 : writeIdxName(file, k->name);
749 498 : writeIdxName(file, k->type);
750 : }
751 288 : write32(file, j->exceptions.size());
752 1041 : for (std::vector< OUString >::const_iterator k(
753 288 : j->exceptions.begin());
754 694 : k != j->exceptions.end(); ++k)
755 : {
756 59 : writeIdxName(file, *k);
757 : }
758 288 : writeAnnotations(file, ann, j->annotations);
759 : }
760 : }
761 493 : writeAnnotations(file, ann, ent2->getAnnotations());
762 493 : break;
763 : }
764 : case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
765 : {
766 : rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
767 : static_cast< unoidl::AccumulationBasedServiceEntity * >(
768 1027 : i->second.entity.get()));
769 1027 : bool ann = !ent2->getAnnotations().empty();
770 5291 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
771 1027 : j(ent2->getDirectMandatoryBaseServices().begin());
772 5209 : !ann && j != ent2->getDirectMandatoryBaseServices().end();
773 : ++j)
774 : {
775 723 : ann = !j->annotations.empty();
776 : }
777 3306 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
778 1027 : j(ent2->getDirectOptionalBaseServices().begin());
779 3222 : !ann && j != ent2->getDirectOptionalBaseServices().end();
780 : ++j)
781 : {
782 61 : ann = !j->annotations.empty();
783 : }
784 7583 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
785 1027 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
786 2513 : (!ann
787 10008 : && j != ent2->getDirectMandatoryBaseInterfaces().end());
788 : ++j)
789 : {
790 1486 : ann = !j->annotations.empty();
791 : }
792 3944 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
793 1027 : j(ent2->getDirectOptionalBaseInterfaces().begin());
794 3850 : !ann && j != ent2->getDirectOptionalBaseInterfaces().end();
795 : ++j)
796 : {
797 272 : ann = !j->annotations.empty();
798 : }
799 11793 : for (std::vector<
800 : unoidl::AccumulationBasedServiceEntity::Property >::
801 : const_iterator j(
802 1027 : ent2->getDirectProperties().begin());
803 11673 : !ann && j != ent2->getDirectProperties().end(); ++j)
804 : {
805 2884 : ann = !j->annotations.empty();
806 : }
807 1027 : i->second.dataOffset = getOffset(file);
808 1027 : writeKind(file, ent2.get(), ann);
809 1027 : write32(file, ent2->getDirectMandatoryBaseServices().size());
810 5277 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
811 1027 : j(ent2->getDirectMandatoryBaseServices().begin());
812 3518 : j != ent2->getDirectMandatoryBaseServices().end(); ++j)
813 : {
814 732 : writeIdxName(file, j->name);
815 732 : writeAnnotations(file, ann, j->annotations);
816 : }
817 1027 : write32(file, ent2->getDirectOptionalBaseServices().size());
818 3267 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
819 1027 : j(ent2->getDirectOptionalBaseServices().begin());
820 2178 : j != ent2->getDirectOptionalBaseServices().end(); ++j)
821 : {
822 62 : writeIdxName(file, j->name);
823 62 : writeAnnotations(file, ann, j->annotations);
824 : }
825 1027 : write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
826 7761 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
827 1027 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
828 5174 : j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j)
829 : {
830 1560 : writeIdxName(file, j->name);
831 1560 : writeAnnotations(file, ann, j->annotations);
832 : }
833 1027 : write32(file, ent2->getDirectOptionalBaseInterfaces().size());
834 3954 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
835 1027 : j(ent2->getDirectOptionalBaseInterfaces().begin());
836 2636 : j != ent2->getDirectOptionalBaseInterfaces().end(); ++j)
837 : {
838 291 : writeIdxName(file, j->name);
839 291 : writeAnnotations(file, ann, j->annotations);
840 : }
841 1027 : write32(file, ent2->getDirectProperties().size());
842 12387 : for (std::vector<
843 : unoidl::AccumulationBasedServiceEntity::Property >::
844 : const_iterator j(
845 1027 : ent2->getDirectProperties().begin());
846 8258 : j != ent2->getDirectProperties().end(); ++j)
847 : {
848 3102 : write16(file, static_cast< sal_uInt16 >(j->attributes));
849 3102 : writeIdxName(file, j->name);
850 3102 : writeIdxName(file, j->type);
851 3102 : writeAnnotations(file, ann, j->annotations);
852 : }
853 1027 : writeAnnotations(file, ann, ent2->getAnnotations());
854 1027 : break;
855 : }
856 : case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
857 : {
858 : rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2(
859 : static_cast< unoidl::InterfaceBasedSingletonEntity * >(
860 164 : i->second.entity.get()));
861 164 : bool ann = !ent2->getAnnotations().empty();
862 164 : i->second.dataOffset = getOffset(file);
863 164 : writeKind(file, ent2.get(), ann);
864 164 : writeIdxName(file, ent2->getBase());
865 164 : writeAnnotations(file, ann, ent2->getAnnotations());
866 164 : break;
867 : }
868 : case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
869 : {
870 : rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2(
871 : static_cast< unoidl::ServiceBasedSingletonEntity * >(
872 1 : i->second.entity.get()));
873 1 : bool ann = !ent2->getAnnotations().empty();
874 1 : i->second.dataOffset = getOffset(file);
875 1 : writeKind(file, ent2.get(), ann);
876 1 : writeIdxName(file, ent2->getBase());
877 1 : writeAnnotations(file, ann, ent2->getAnnotations());
878 1 : break;
879 : }
880 : }
881 : }
882 6039 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
883 : ++i)
884 : {
885 5858 : i->second.nameOffset = writeNulName(file, i->first);
886 : }
887 181 : sal_uInt64 off = getOffset(file);
888 181 : if (rootSize == 0) {
889 173 : write8(file, 0); // SORT_MODULE
890 173 : write32(file, map.size());
891 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
892 : } else {
893 8 : *rootSize = map.size();
894 : // overflow from std::map::size_type -> std::size_t is unrealistic
895 : }
896 6039 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
897 : ++i)
898 : {
899 5858 : write32(file, i->second.nameOffset);
900 5858 : write32(file, i->second.dataOffset);
901 : }
902 181 : return off;
903 : }
904 :
905 : }
906 :
907 16 : SAL_IMPLEMENT_MAIN() {
908 8 : sal_uInt32 args = rtl_getAppCommandArgCount();
909 8 : if (args < 2) {
910 : std::cerr
911 0 : << "Usage: reg2unoidl <extra .rdb files> <.rdb file> <unoidl file>"
912 0 : << std::endl;
913 0 : std::exit(EXIT_FAILURE);
914 : }
915 8 : rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
916 17 : for (sal_uInt32 i = 0; i != args - 2; ++i) {
917 9 : mgr->addProvider(load(mgr, getArgumentUri(i)));
918 : }
919 : rtl::Reference< unoidl::Provider > prov(
920 16 : load(mgr, getArgumentUri(args - 2)));
921 16 : osl::File f(getArgumentUri(args - 1));
922 8 : osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
923 8 : if (e == osl::FileBase::E_NOENT) {
924 8 : e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
925 : }
926 8 : if (e != osl::FileBase::E_None) {
927 : std::cerr
928 0 : << "Cannot open <" << f.getURL() << "> for writing, error code "
929 0 : << +e << std::endl;
930 0 : std::exit(EXIT_FAILURE);
931 : }
932 8 : write(f, "UNOIDL\xFF\0", 8);
933 8 : write32(f, 0); // root map offset
934 8 : write32(f, 0); // root map size
935 : write(
936 : f,
937 8 : RTL_CONSTASCII_STRINGPARAM(
938 : "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
939 8 : " reg2unoidl **\0"));
940 : sal_uInt64 off;
941 : std::size_t size;
942 : try {
943 8 : off = writeMap(f, prov->createRootCursor(), &size);
944 0 : } catch (unoidl::FileFormatException & e1) {
945 : std::cerr
946 0 : << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
947 0 : << std::endl;
948 0 : std::exit(EXIT_FAILURE);
949 : }
950 8 : e = f.setSize(getOffset(f)); // truncate in case it already existed
951 8 : if (e != osl::FileBase::E_None) {
952 : std::cerr
953 0 : << "Cannot set size of <" << f.getURL() << ">, error code " << +e
954 0 : << std::endl;
955 0 : std::exit(EXIT_FAILURE);
956 : }
957 8 : e = f.setPos(osl_Pos_Absolut, 8);
958 8 : if (e != osl::FileBase::E_None) {
959 : std::cerr
960 0 : << "Cannot rewind current position in <" << f.getURL()
961 0 : << ">, error code " << +e << std::endl;
962 0 : std::exit(EXIT_FAILURE);
963 : }
964 8 : write32(f, off);
965 8 : write32(f, size);
966 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
967 8 : e = f.close();
968 8 : if (e != osl::FileBase::E_None) {
969 : std::cerr
970 0 : << "Cannot close <" << f.getURL() << "> after writing, error code "
971 0 : << +e << std::endl;
972 0 : std::exit(EXIT_FAILURE);
973 : }
974 16 : return EXIT_SUCCESS;
975 24 : }
976 :
977 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|