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 0 : void badUsage() {
38 : std::cerr
39 0 : << "Usage:" << std::endl << std::endl
40 0 : << " unoidl-write [<registries>] [@<entities file>] <unoidl file>"
41 0 : << std::endl << std::endl
42 : << ("where each <registry> is either a new- or legacy-format .rdb file,"
43 0 : " a single .idl")
44 0 : << std::endl
45 : << ("file, or a root directory of an .idl file tree; and the UTF-8"
46 0 : " encoded <entities")
47 0 : << std::endl
48 : << ("file> contains zero or more space-separated names of (non-module)"
49 0 : " entities to")
50 0 : << std::endl
51 : << ("include in the output, and, if omitted, defaults to the complete"
52 0 : " content of the")
53 0 : << std::endl << "last <registry>, if any." << std::endl;
54 0 : std::exit(EXIT_FAILURE);
55 : }
56 :
57 838 : OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
58 838 : OUString arg;
59 838 : rtl_getAppCommandArg(argument, &arg.pData);
60 838 : if (arg.startsWith("@", &arg)) {
61 5 : if (entities == 0) {
62 0 : badUsage();
63 : }
64 5 : *entities = true;
65 833 : } else if (entities != 0) {
66 334 : *entities = false;
67 : }
68 1676 : OUString url;
69 838 : osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
70 838 : if (e1 != osl::FileBase::E_None) {
71 : std::cerr
72 0 : << "Cannot convert \"" << arg << "\" to file URL, error code "
73 0 : << +e1 << std::endl;
74 0 : std::exit(EXIT_FAILURE);
75 : }
76 1676 : OUString cwd;
77 838 : oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
78 838 : if (e2 != osl_Process_E_None) {
79 : std::cerr
80 0 : << "Cannot obtain working directory, error code " << +e2
81 0 : << std::endl;
82 0 : std::exit(EXIT_FAILURE);
83 : }
84 838 : OUString abs;
85 838 : e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
86 838 : if (e1 != osl::FileBase::E_None) {
87 : std::cerr
88 0 : << "Cannot make \"" << url
89 0 : << "\" into an absolute file URL, error code " << +e1 << std::endl;
90 0 : std::exit(EXIT_FAILURE);
91 : }
92 1676 : return abs;
93 : }
94 :
95 52579 : sal_uInt64 getOffset(osl::File & file) {
96 : sal_uInt64 off;
97 52579 : osl::FileBase::RC e = file.getPos(off);
98 52579 : if (e != osl::FileBase::E_None) {
99 : std::cerr
100 0 : << "Cannot determine current position in <" << file.getURL()
101 0 : << ">, error code " << +e << std::endl;
102 0 : std::exit(EXIT_FAILURE);
103 : }
104 52579 : return off;
105 : }
106 :
107 199899 : void write(osl::File & file, void const * buffer, sal_uInt64 size) {
108 : sal_uInt64 n;
109 199899 : osl::FileBase::RC e = file.write(buffer, size, n);
110 199899 : if (e != osl::FileBase::E_None) {
111 : std::cerr
112 0 : << "Cannot write to <" << file.getURL() << ">, error code " << +e
113 0 : << std::endl;
114 0 : std::exit(EXIT_FAILURE);
115 : }
116 199899 : if (n != size) {
117 : std::cerr
118 0 : << "Bad write of " << n << " instead of " << size << " bytes to <"
119 0 : << file.getURL() << '>' << std::endl;
120 0 : std::exit(EXIT_FAILURE);
121 : }
122 199899 : }
123 :
124 27401 : void write8(osl::File & file, sal_uInt64 value) {
125 27401 : if (value > 0xFF) {
126 : std::cerr
127 0 : << "Cannot write value >= 2^8; input is too large" << std::endl;
128 0 : std::exit(EXIT_FAILURE);
129 : }
130 : unsigned char buf[1];
131 27401 : buf[0] = value & 0xFF;
132 27401 : write(file, buf, SAL_N_ELEMENTS(buf));
133 27401 : }
134 :
135 5247 : void write16(osl::File & file, sal_uInt64 value) {
136 5247 : if (value > 0xFFFF) {
137 : std::cerr
138 0 : << "Cannot write value >= 2^16; input is too large" << std::endl;
139 0 : std::exit(EXIT_FAILURE);
140 : }
141 : unsigned char buf[2];
142 5247 : buf[0] = value & 0xFF;
143 5247 : buf[1] = (value >> 8) & 0xFF;
144 5247 : write(file, buf, SAL_N_ELEMENTS(buf));
145 5247 : }
146 :
147 132881 : void write32(osl::File & file, sal_uInt64 value) {
148 132881 : if (value > 0xFFFFFFFF) {
149 : std::cerr
150 0 : << "Cannot write value >= 2^32; input is too large" << std::endl;
151 0 : std::exit(EXIT_FAILURE);
152 : }
153 : unsigned char buf[4];
154 132881 : buf[0] = value & 0xFF;
155 132881 : buf[1] = (value >> 8) & 0xFF;
156 132881 : buf[2] = (value >> 16) & 0xFF;
157 132881 : buf[3] = (value >> 24) & 0xFF;
158 132881 : write(file, buf, SAL_N_ELEMENTS(buf));
159 132881 : }
160 :
161 46 : void write64(osl::File & file, sal_uInt64 value) {
162 : unsigned char buf[8];
163 46 : buf[0] = value & 0xFF;
164 46 : buf[1] = (value >> 8) & 0xFF;
165 46 : buf[2] = (value >> 16) & 0xFF;
166 46 : buf[3] = (value >> 24) & 0xFF;
167 46 : buf[4] = (value >> 32) & 0xFF;
168 46 : buf[5] = (value >> 40) & 0xFF;
169 46 : buf[6] = (value >> 48) & 0xFF;
170 46 : buf[7] = (value >> 56) & 0xFF;
171 46 : write(file, buf, SAL_N_ELEMENTS(buf));
172 46 : }
173 :
174 21 : void writeIso60599Binary32(osl::File & file, float value) {
175 : union {
176 : unsigned char buf[4];
177 : float f; // assuming float is ISO 60599 binary32
178 : } sa;
179 21 : sa.f = value;
180 : #if defined OSL_BIGENDIAN
181 : std::swap(sa.buf[0], sa.buf[3]);
182 : std::swap(sa.buf[1], sa.buf[2]);
183 : #endif
184 21 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
185 21 : }
186 :
187 1 : void writeIso60599Binary64(osl::File & file, double value) {
188 : union {
189 : unsigned char buf[8];
190 : float d; // assuming double is ISO 60599 binary64
191 : } sa;
192 1 : sa.d = value;
193 : #if defined OSL_BIGENDIAN
194 : std::swap(sa.buf[0], sa.buf[7]);
195 : std::swap(sa.buf[1], sa.buf[6]);
196 : std::swap(sa.buf[2], sa.buf[5]);
197 : std::swap(sa.buf[3], sa.buf[4]);
198 : #endif
199 1 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
200 1 : }
201 :
202 69616 : OString toAscii(OUString const & name) {
203 69616 : OString ascii;
204 69616 : if (!name.convertToString(
205 : &ascii, RTL_TEXTENCODING_ASCII_US,
206 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
207 69616 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
208 : {
209 : std::cerr
210 0 : << "Cannot convert \"" << name << "\" to US ASCII" << std::endl;
211 0 : std::exit(EXIT_FAILURE);
212 : }
213 69616 : return ascii;
214 : }
215 :
216 281 : OString toUtf8(OUString const & string) {
217 281 : OString ascii;
218 281 : if (!string.convertToString(
219 : &ascii, RTL_TEXTENCODING_UTF8,
220 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
221 281 : | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
222 : {
223 : std::cerr
224 0 : << "Cannot convert \"" << string << "\" to UTF-8" << std::endl;
225 0 : std::exit(EXIT_FAILURE);
226 : }
227 281 : return ascii;
228 : }
229 :
230 18277 : sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
231 18277 : OString ascii(toAscii(name));
232 18277 : if (ascii.indexOf('\0') != -1) {
233 : std::cerr
234 0 : << "Name \"" << ascii << "\" contains NUL characters" << std::endl;
235 0 : std::exit(EXIT_FAILURE);
236 : }
237 18277 : sal_uInt64 off = getOffset(file);
238 18277 : write(file, ascii.getStr(), ascii.getLength() + 1);
239 18277 : return off;
240 : }
241 :
242 51620 : void writeIdxString(osl::File & file, OString const & string) {
243 51620 : static std::map< OString, sal_uInt64 > reuse;
244 51620 : std::map< OString, sal_uInt64 >::iterator i(reuse.find(string));
245 51620 : if (i == reuse.end()) {
246 15717 : reuse.insert(std::make_pair(string, getOffset(file)));
247 : assert(
248 : (static_cast< sal_uInt64 >(string.getLength()) & 0x80000000) == 0);
249 15717 : write32(file, static_cast< sal_uInt64 >(string.getLength()));
250 15717 : write(file, string.getStr(), string.getLength());
251 : } else {
252 35903 : if ((i->second & 0x80000000) != 0) {
253 : std::cerr
254 0 : << "Cannot write index 0x" << std::hex << i->second << std::dec
255 0 : << " of \"" << string << "\"; input is too large" << std::endl;
256 0 : std::exit(EXIT_FAILURE);
257 : }
258 35903 : write32(file, i->second | 0x80000000);
259 : }
260 51620 : }
261 :
262 51339 : void writeIdxName(osl::File & file, OUString const & name) {
263 51339 : writeIdxString(file, toAscii(name));
264 51339 : }
265 :
266 37194 : void writeAnnotations(
267 : osl::File & file, bool annotate,
268 : std::vector< OUString > const & annotations)
269 : {
270 : assert(annotate || annotations.empty());
271 37194 : if (annotate) {
272 1394 : write32(file, annotations.size());
273 : // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
274 5025 : for (std::vector< OUString >::const_iterator i(annotations.begin());
275 3350 : i != annotations.end(); ++i)
276 : {
277 281 : writeIdxString(file, toUtf8(*i));
278 : }
279 : }
280 37194 : }
281 :
282 6059 : void writeKind(
283 : osl::File & file,
284 : rtl::Reference< unoidl::PublishableEntity > const & entity,
285 : bool annotated, bool flag = false)
286 : {
287 : assert(entity.is());
288 6059 : sal_uInt64 v = entity->getSort();
289 6059 : if (entity->isPublished()) {
290 2785 : v |= 0x80;
291 : }
292 6059 : if (annotated) {
293 228 : v |= 0x40;
294 : }
295 6059 : if (flag) {
296 599 : v |= 0x20;
297 : }
298 6059 : write8(file, v);
299 6059 : }
300 :
301 31548 : struct Item {
302 6310 : explicit Item(rtl::Reference< unoidl::Entity > const & theEntity):
303 6310 : entity(theEntity), nameOffset(0), dataOffset(0)
304 6310 : {}
305 :
306 : rtl::Reference< unoidl::Entity > entity;
307 : std::map< OUString, Item > module;
308 : sal_uInt64 nameOffset;
309 : sal_uInt64 dataOffset;
310 : };
311 :
312 59840 : struct ConstItem {
313 11968 : ConstItem(
314 : unoidl::ConstantValue const & theConstant,
315 : std::vector< OUString > const & theAnnotations):
316 : constant(theConstant), annotations(theAnnotations), nameOffset(0),
317 11968 : dataOffset(0)
318 11968 : {}
319 :
320 : unoidl::ConstantValue constant;
321 : std::vector< OUString > annotations;
322 : sal_uInt64 nameOffset;
323 : sal_uInt64 dataOffset;
324 : };
325 :
326 5 : void mapEntities(
327 : rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
328 : std::map< OUString, Item > & map)
329 : {
330 : assert(manager.is());
331 5 : osl::File f(uri);
332 5 : osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
333 5 : if (e != osl::FileBase::E_None) {
334 : std::cerr
335 0 : << "Cannot open <" << f.getURL() << "> for reading, error code "
336 0 : << +e << std::endl;
337 0 : std::exit(EXIT_FAILURE);
338 : }
339 : for (;;) {
340 : sal_Bool eof;
341 10 : e = f.isEndOfFile(&eof);
342 10 : if (e != osl::FileBase::E_None) {
343 : std::cerr
344 0 : << "Cannot check <" << f.getURL() << "> for EOF, error code "
345 0 : << +e << std::endl;
346 0 : std::exit(EXIT_FAILURE);
347 : }
348 10 : if (eof) {
349 5 : break;
350 : }
351 5 : rtl::ByteSequence s1;
352 5 : e = f.readLine(s1);
353 5 : if (e != osl::FileBase::E_None) {
354 : std::cerr
355 0 : << "Cannot read from <" << f.getURL() << ">, error code "
356 0 : << +e << std::endl;
357 0 : std::exit(EXIT_FAILURE);
358 : }
359 10 : OUString s2;
360 5 : if (!rtl_convertStringToUString(
361 5 : &s2.pData, reinterpret_cast< char const * >(s1.getConstArray()),
362 : s1.getLength(), RTL_TEXTENCODING_UTF8,
363 : (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
364 : | RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
365 10 : | RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
366 : {
367 : std::cerr
368 0 : << "Cannot interpret line read from <" << f.getURL()
369 0 : << "> as UTF-8" << std::endl;
370 0 : std::exit(EXIT_FAILURE);
371 : }
372 5357 : for (sal_Int32 i = 0; i != -1;) {
373 5347 : OUString t(s2.getToken(0, ' ', i));
374 5347 : if (!t.isEmpty()) {
375 5342 : rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
376 5342 : if (!ent.is()) {
377 : std::cerr
378 0 : << "Unknown entity \"" << t << "\" read from <"
379 0 : << f.getURL() << ">" << std::endl;
380 0 : std::exit(EXIT_FAILURE);
381 : }
382 5342 : if (ent->getSort() == unoidl::Entity::SORT_MODULE) {
383 : std::cerr
384 0 : << "Module entity \"" << t << "\" read from <"
385 0 : << f.getURL() << ">" << std::endl;
386 0 : std::exit(EXIT_FAILURE);
387 : }
388 5342 : std::map< OUString, Item > * map2 = ↦
389 5342 : for (sal_Int32 j = 0;;) {
390 26363 : OUString id(t.getToken(0, '.', j));
391 26363 : if (j == -1) {
392 5342 : map2->insert(std::make_pair(id, Item(ent)));
393 5342 : break;
394 : }
395 21021 : std::map< OUString, Item >::iterator k(map2->find(id));
396 21021 : if (k == map2->end()) {
397 : rtl::Reference< unoidl::Entity > ent2(
398 150 : manager->findEntity(t.copy(0, j - 1)));
399 : assert(ent2.is());
400 150 : k = map2->insert(std::make_pair(id, Item(ent2))).first;
401 : }
402 : assert(
403 : k->second.entity->getSort()
404 : == unoidl::Entity::SORT_MODULE);
405 21021 : map2 = &k->second.module;
406 21021 : }
407 : }
408 5347 : }
409 5 : }
410 10 : e = f.close();
411 5 : if (e != osl::FileBase::E_None) {
412 : std::cerr
413 0 : << "Cannot close <" << f.getURL() << "> after reading, error code "
414 0 : << +e << std::endl;
415 0 : std::exit(EXIT_FAILURE);
416 5 : }
417 5 : }
418 :
419 249 : void mapCursor(
420 : rtl::Reference< unoidl::MapCursor > const & cursor,
421 : std::map< OUString, Item > & map)
422 : {
423 249 : if (cursor.is()) {
424 : for (;;) {
425 1067 : OUString name;
426 1885 : rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
427 1067 : if (!ent.is()) {
428 249 : break;
429 : }
430 : std::pair< std::map< OUString, Item >::iterator, bool > i(
431 818 : map.insert(std::make_pair(name, Item(ent))));
432 818 : if (!i.second) {
433 0 : std::cout << "Duplicate name \"" << name << '"' << std::endl;
434 0 : std::exit(EXIT_FAILURE);
435 : }
436 818 : if (i.first->second.entity->getSort()
437 : == unoidl::Entity::SORT_MODULE)
438 : {
439 : mapCursor(
440 : rtl::Reference< unoidl::ModuleEntity >(
441 : static_cast< unoidl::ModuleEntity * >(
442 200 : i.first->second.entity.get()))->createCursor(),
443 200 : i.first->second.module);
444 : }
445 818 : }
446 : }
447 249 : }
448 :
449 404 : sal_uInt64 writeMap(
450 : osl::File & file, std::map< OUString, Item > & map, std::size_t * rootSize)
451 : {
452 6713 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
453 : ++i)
454 : {
455 6309 : switch (i->second.entity->getSort()) {
456 : case unoidl::Entity::SORT_MODULE:
457 250 : i->second.dataOffset = writeMap(file, i->second.module, 0);
458 250 : break;
459 : case unoidl::Entity::SORT_ENUM_TYPE:
460 : {
461 : rtl::Reference< unoidl::EnumTypeEntity > ent2(
462 : static_cast< unoidl::EnumTypeEntity * >(
463 226 : i->second.entity.get()));
464 226 : bool ann = !ent2->getAnnotations().empty();
465 4615 : for (std::vector< unoidl::EnumTypeEntity::Member >::
466 226 : const_iterator j(ent2->getMembers().begin());
467 4583 : !ann && j != ent2->getMembers().end(); ++j)
468 : {
469 1307 : ann = !j->annotations.empty();
470 : }
471 226 : i->second.dataOffset = getOffset(file);
472 226 : writeKind(file, ent2.get(), ann);
473 226 : write32(file, ent2->getMembers().size());
474 4785 : for (std::vector< unoidl::EnumTypeEntity::Member >::
475 226 : const_iterator j(ent2->getMembers().begin());
476 3190 : j != ent2->getMembers().end(); ++j)
477 : {
478 1369 : writeIdxName(file, j->name);
479 1369 : write32(file, static_cast< sal_uInt32 >(j->value));
480 1369 : writeAnnotations(file, ann, j->annotations);
481 : }
482 226 : writeAnnotations(file, ann, ent2->getAnnotations());
483 226 : break;
484 : }
485 : case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
486 : {
487 : rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
488 : static_cast< unoidl::PlainStructTypeEntity * >(
489 443 : i->second.entity.get()));
490 443 : bool ann = !ent2->getAnnotations().empty();
491 5718 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
492 443 : const_iterator j(ent2->getDirectMembers().begin());
493 5688 : !ann && j != ent2->getDirectMembers().end(); ++j)
494 : {
495 1458 : ann = !j->annotations.empty();
496 : }
497 443 : i->second.dataOffset = getOffset(file);
498 : writeKind(
499 443 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
500 443 : if (!ent2->getDirectBase().isEmpty()) {
501 107 : writeIdxName(file, ent2->getDirectBase());
502 : }
503 443 : write32(file, ent2->getDirectMembers().size());
504 5868 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
505 443 : const_iterator j(ent2->getDirectMembers().begin());
506 3912 : j != ent2->getDirectMembers().end(); ++j)
507 : {
508 1513 : writeIdxName(file, j->name);
509 1513 : writeIdxName(file, j->type);
510 1513 : writeAnnotations(file, ann, j->annotations);
511 : }
512 443 : writeAnnotations(file, ann, ent2->getAnnotations());
513 443 : break;
514 : }
515 : case unoidl::Entity::SORT_POLYMORPHIC_STRUCT_TYPE_TEMPLATE:
516 : {
517 : rtl::Reference< unoidl::PolymorphicStructTypeTemplateEntity >
518 : ent2(
519 : static_cast<
520 : unoidl::PolymorphicStructTypeTemplateEntity * >(
521 33 : i->second.entity.get()));
522 33 : bool ann = !ent2->getAnnotations().empty();
523 216 : for (std::vector<
524 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
525 : const_iterator j(
526 33 : ent2->getMembers().begin());
527 216 : !ann && j != ent2->getMembers().end(); ++j)
528 : {
529 39 : ann = !j->annotations.empty();
530 : }
531 33 : i->second.dataOffset = getOffset(file);
532 33 : writeKind(file, ent2.get(), ann);
533 33 : write32(file, ent2->getTypeParameters().size());
534 207 : for (std::vector< OUString >::const_iterator j(
535 33 : ent2->getTypeParameters().begin());
536 138 : j != ent2->getTypeParameters().end(); ++j)
537 : {
538 36 : writeIdxName(file, *j);
539 : }
540 33 : write32(file, ent2->getMembers().size());
541 216 : for (std::vector<
542 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
543 : const_iterator j(
544 33 : ent2->getMembers().begin());
545 144 : j != ent2->getMembers().end(); ++j)
546 : {
547 39 : sal_uInt64 f = 0;
548 39 : if (j->parameterized) {
549 24 : f |= 0x01;
550 : }
551 39 : write8(file, f);
552 39 : writeIdxName(file, j->name);
553 39 : writeIdxName(file, j->type);
554 39 : writeAnnotations(file, ann, j->annotations);
555 : }
556 33 : writeAnnotations(file, ann, ent2->getAnnotations());
557 33 : break;
558 : }
559 : case unoidl::Entity::SORT_EXCEPTION_TYPE:
560 : {
561 : rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
562 : static_cast< unoidl::ExceptionTypeEntity * >(
563 277 : i->second.entity.get()));
564 277 : bool ann = !ent2->getAnnotations().empty();
565 1319 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
566 277 : const_iterator j(ent2->getDirectMembers().begin());
567 1315 : !ann && j != ent2->getDirectMembers().end(); ++j)
568 : {
569 162 : ann = !j->annotations.empty();
570 : }
571 277 : i->second.dataOffset = getOffset(file);
572 : writeKind(
573 277 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
574 277 : if (!ent2->getDirectBase().isEmpty()) {
575 252 : writeIdxName(file, ent2->getDirectBase());
576 : }
577 277 : write32(file, ent2->getDirectMembers().size());
578 1320 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
579 277 : const_iterator j(ent2->getDirectMembers().begin());
580 880 : j != ent2->getDirectMembers().end(); ++j)
581 : {
582 163 : writeIdxName(file, j->name);
583 163 : writeIdxName(file, j->type);
584 163 : writeAnnotations(file, ann, j->annotations);
585 : }
586 277 : writeAnnotations(file, ann, ent2->getAnnotations());
587 277 : break;
588 : }
589 : case unoidl::Entity::SORT_INTERFACE_TYPE:
590 : {
591 : rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
592 : static_cast< unoidl::InterfaceTypeEntity * >(
593 2053 : i->second.entity.get()));
594 2053 : bool ann = !ent2->getAnnotations().empty();
595 12882 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
596 2053 : j(ent2->getDirectMandatoryBases().begin());
597 12690 : !ann && j != ent2->getDirectMandatoryBases().end(); ++j)
598 : {
599 2209 : ann = !j->annotations.empty();
600 : }
601 6357 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
602 2053 : j(ent2->getDirectOptionalBases().begin());
603 6165 : !ann && j != ent2->getDirectOptionalBases().end(); ++j)
604 : {
605 34 : ann = !j->annotations.empty();
606 : }
607 9878 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
608 2053 : const_iterator j(ent2->getDirectAttributes().begin());
609 9682 : !ann && j != ent2->getDirectAttributes().end(); ++j)
610 : {
611 1207 : ann = !j->annotations.empty();
612 : }
613 24456 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
614 2053 : const_iterator j(ent2->getDirectMethods().begin());
615 24246 : !ann && j != ent2->getDirectMethods().end(); ++j)
616 : {
617 6064 : ann = !j->annotations.empty();
618 : }
619 2053 : i->second.dataOffset = getOffset(file);
620 2053 : writeKind(file, ent2.get(), ann);
621 2053 : write32(file, ent2->getDirectMandatoryBases().size());
622 13077 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
623 2053 : j(ent2->getDirectMandatoryBases().begin());
624 8718 : j != ent2->getDirectMandatoryBases().end(); ++j)
625 : {
626 2306 : writeIdxName(file, j->name);
627 2306 : writeAnnotations(file, ann, j->annotations);
628 : }
629 2053 : write32(file, ent2->getDirectOptionalBases().size());
630 6261 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
631 2053 : j(ent2->getDirectOptionalBases().begin());
632 4174 : j != ent2->getDirectOptionalBases().end(); ++j)
633 : {
634 34 : writeIdxName(file, j->name);
635 34 : writeAnnotations(file, ann, j->annotations);
636 : }
637 2053 : write32(file, ent2->getDirectAttributes().size());
638 9828 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
639 2053 : const_iterator j(ent2->getDirectAttributes().begin());
640 6552 : j != ent2->getDirectAttributes().end(); ++j)
641 : {
642 1223 : sal_uInt64 f = 0;
643 1223 : if (j->bound) {
644 157 : f |= 0x01;
645 : }
646 1223 : if (j->readOnly) {
647 272 : f |= 0x02;
648 : }
649 1223 : write8(file, f);
650 1223 : writeIdxName(file, j->name);
651 1223 : writeIdxName(file, j->type);
652 1223 : write32(file, j->getExceptions.size());
653 3966 : for (std::vector< OUString >::const_iterator k(
654 1223 : j->getExceptions.begin());
655 2644 : k != j->getExceptions.end(); ++k)
656 : {
657 99 : writeIdxName(file, *k);
658 : }
659 1223 : if (!j->readOnly) {
660 951 : write32(file, j->setExceptions.size());
661 3228 : for (std::vector< OUString >::const_iterator k(
662 951 : j->setExceptions.begin());
663 2152 : k != j->setExceptions.end(); ++k)
664 : {
665 125 : writeIdxName(file, *k);
666 : }
667 : }
668 1223 : writeAnnotations(file, ann, j->annotations);
669 : }
670 2053 : write32(file, ent2->getDirectMethods().size());
671 25341 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
672 2053 : const_iterator j(ent2->getDirectMethods().begin());
673 16894 : j != ent2->getDirectMethods().end(); ++j)
674 : {
675 6394 : writeIdxName(file, j->name);
676 6394 : writeIdxName(file, j->returnType);
677 6394 : write32(file, j->parameters.size());
678 40461 : for (std::vector<
679 : unoidl::InterfaceTypeEntity::Method::Parameter >::
680 6394 : const_iterator k(j->parameters.begin());
681 26974 : k != j->parameters.end(); ++k)
682 : {
683 7093 : write8(file, k->direction);
684 7093 : writeIdxName(file, k->name);
685 7093 : writeIdxName(file, k->type);
686 : }
687 6394 : write32(file, j->exceptions.size());
688 28194 : for (std::vector< OUString >::const_iterator k(
689 6394 : j->exceptions.begin());
690 18796 : k != j->exceptions.end(); ++k)
691 : {
692 3004 : writeIdxName(file, *k);
693 : }
694 6394 : writeAnnotations(file, ann, j->annotations);
695 : }
696 2053 : writeAnnotations(file, ann, ent2->getAnnotations());
697 2053 : break;
698 : }
699 : case unoidl::Entity::SORT_TYPEDEF:
700 : {
701 : rtl::Reference< unoidl::TypedefEntity > ent2(
702 : static_cast< unoidl::TypedefEntity * >(
703 72 : i->second.entity.get()));
704 72 : bool ann = !ent2->getAnnotations().empty();
705 72 : i->second.dataOffset = getOffset(file);
706 72 : writeKind(file, ent2.get(), ann);
707 72 : writeIdxName(file, ent2->getType());
708 72 : writeAnnotations(file, ann, ent2->getAnnotations());
709 72 : break;
710 : }
711 : case unoidl::Entity::SORT_CONSTANT_GROUP:
712 : {
713 : rtl::Reference< unoidl::ConstantGroupEntity > ent2(
714 : static_cast< unoidl::ConstantGroupEntity * >(
715 1204 : i->second.entity.get()));
716 2408 : std::map< OUString, ConstItem > cmap;
717 39516 : for (std::vector< unoidl::ConstantGroupEntity::Member >::
718 1204 : const_iterator j(ent2->getMembers().begin());
719 26344 : j != ent2->getMembers().end(); ++j)
720 : {
721 23936 : if (!cmap.insert(
722 : std::make_pair(
723 23936 : j->name, ConstItem(j->value, j->annotations))).
724 11968 : second)
725 : {
726 : std::cout
727 0 : << "Duplicate constant group member name \""
728 0 : << j->name << '"' << std::endl;
729 0 : std::exit(EXIT_FAILURE);
730 : }
731 : }
732 39516 : for (std::map< OUString, ConstItem >::iterator j(cmap.begin());
733 26344 : j != cmap.end(); ++j)
734 : {
735 11968 : j->second.dataOffset = getOffset(file);
736 11968 : sal_uInt64 v = j->second.constant.type;
737 11968 : if (!j->second.annotations.empty()) {
738 14 : v |= 0x80;
739 : }
740 11968 : write8(file, v);
741 11968 : switch (j->second.constant.type) {
742 : case unoidl::ConstantValue::TYPE_BOOLEAN:
743 1 : write8(file, j->second.constant.booleanValue ? 1 : 0);
744 1 : break;
745 : case unoidl::ConstantValue::TYPE_BYTE:
746 : write8(
747 : file,
748 : static_cast< sal_uInt8 >(
749 254 : j->second.constant.byteValue));
750 254 : break;
751 : case unoidl::ConstantValue::TYPE_SHORT:
752 : write16(
753 : file,
754 : static_cast< sal_uInt16 >(
755 2075 : j->second.constant.shortValue));
756 2075 : break;
757 : case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
758 8 : write16(file, j->second.constant.unsignedShortValue);
759 8 : break;
760 : case unoidl::ConstantValue::TYPE_LONG:
761 : write32(
762 : file,
763 : static_cast< sal_uInt32 >(
764 9554 : j->second.constant.longValue));
765 9554 : break;
766 : case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
767 8 : write32(file, j->second.constant.unsignedLongValue);
768 8 : break;
769 : case unoidl::ConstantValue::TYPE_HYPER:
770 : write64(
771 : file,
772 : static_cast< sal_uInt64 >(
773 38 : j->second.constant.hyperValue));
774 38 : break;
775 : case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
776 8 : write64(file, j->second.constant.unsignedHyperValue);
777 8 : break;
778 : case unoidl::ConstantValue::TYPE_FLOAT:
779 : writeIso60599Binary32(
780 21 : file, j->second.constant.floatValue);
781 21 : break;
782 : case unoidl::ConstantValue::TYPE_DOUBLE:
783 : writeIso60599Binary64(
784 1 : file, j->second.constant.doubleValue);
785 1 : break;
786 : default:
787 0 : for (;;) { std::abort(); } // this cannot happen
788 : }
789 : writeAnnotations(
790 11968 : file, !j->second.annotations.empty(),
791 23936 : j->second.annotations);
792 : }
793 39516 : for (std::map< OUString, ConstItem >::iterator j(
794 1204 : cmap.begin());
795 26344 : j != cmap.end(); ++j)
796 : {
797 11968 : j->second.nameOffset = writeNulName(file, j->first);
798 : }
799 1204 : bool ann = !ent2->getAnnotations().empty();
800 1204 : i->second.dataOffset = getOffset(file);
801 1204 : writeKind(file, ent2.get(), ann);
802 1204 : write32(file, cmap.size());
803 : // overflow from std::map::size_type -> sal_uInt64 is
804 : // unrealistic
805 39516 : for (std::map< OUString, ConstItem >::iterator j(
806 1204 : cmap.begin());
807 26344 : j != cmap.end(); ++j)
808 : {
809 11968 : write32(file, j->second.nameOffset);
810 11968 : write32(file, j->second.dataOffset);
811 : }
812 1204 : writeAnnotations(file, ann, ent2->getAnnotations());
813 2408 : break;
814 : }
815 : case unoidl::Entity::SORT_SINGLE_INTERFACE_BASED_SERVICE:
816 : {
817 : rtl::Reference< unoidl::SingleInterfaceBasedServiceEntity >
818 : ent2(
819 : static_cast<
820 : unoidl::SingleInterfaceBasedServiceEntity * >(
821 513 : i->second.entity.get()));
822 513 : bool dfltCtor = ent2->getConstructors().size() == 1
823 513 : && ent2->getConstructors()[0].defaultConstructor;
824 513 : bool ann = !ent2->getAnnotations().empty();
825 513 : if (!dfltCtor) {
826 1731 : for (std::vector<
827 : unoidl::SingleInterfaceBasedServiceEntity::
828 : Constructor >::const_iterator j(
829 273 : ent2->getConstructors().begin());
830 1731 : !ann && j != ent2->getConstructors().end(); ++j)
831 : {
832 304 : ann = !j->annotations.empty();
833 : }
834 : }
835 513 : i->second.dataOffset = getOffset(file);
836 513 : writeKind(file, ent2.get(), ann, dfltCtor);
837 513 : writeIdxName(file, ent2->getBase());
838 513 : if (!dfltCtor) {
839 273 : write32(file, ent2->getConstructors().size());
840 1731 : for (std::vector<
841 : unoidl::SingleInterfaceBasedServiceEntity::
842 : Constructor >::const_iterator j(
843 273 : ent2->getConstructors().begin());
844 1154 : j != ent2->getConstructors().end(); ++j)
845 : {
846 304 : if (j->defaultConstructor) {
847 : std::cout
848 0 : << "Unexpected default constructor \""
849 0 : << j->name << '"' << std::endl;
850 0 : std::exit(EXIT_FAILURE);
851 : }
852 304 : writeIdxName(file, j->name);
853 304 : write32(file, j->parameters.size());
854 2454 : for (std::vector<
855 : unoidl::SingleInterfaceBasedServiceEntity::
856 : Constructor::Parameter >::const_iterator k(
857 304 : j->parameters.begin());
858 1636 : k != j->parameters.end(); ++k)
859 : {
860 514 : sal_uInt64 f = 0;
861 514 : if (k->rest) {
862 6 : f |= 0x04;
863 : }
864 514 : write8(file, f);
865 514 : writeIdxName(file, k->name);
866 514 : writeIdxName(file, k->type);
867 : }
868 304 : write32(file, j->exceptions.size());
869 1107 : for (std::vector< OUString >::const_iterator k(
870 304 : j->exceptions.begin());
871 738 : k != j->exceptions.end(); ++k)
872 : {
873 65 : writeIdxName(file, *k);
874 : }
875 304 : writeAnnotations(file, ann, j->annotations);
876 : }
877 : }
878 513 : writeAnnotations(file, ann, ent2->getAnnotations());
879 513 : break;
880 : }
881 : case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
882 : {
883 : rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
884 : static_cast< unoidl::AccumulationBasedServiceEntity * >(
885 1049 : i->second.entity.get()));
886 1049 : bool ann = !ent2->getAnnotations().empty();
887 5369 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
888 1049 : j(ent2->getDirectMandatoryBaseServices().begin());
889 5287 : !ann && j != ent2->getDirectMandatoryBaseServices().end();
890 : ++j)
891 : {
892 727 : ann = !j->annotations.empty();
893 : }
894 3372 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
895 1049 : j(ent2->getDirectOptionalBaseServices().begin());
896 3288 : !ann && j != ent2->getDirectOptionalBaseServices().end();
897 : ++j)
898 : {
899 61 : ann = !j->annotations.empty();
900 : }
901 7667 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
902 1049 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
903 2541 : (!ann
904 10120 : && j != ent2->getDirectMandatoryBaseInterfaces().end());
905 : ++j)
906 : {
907 1492 : ann = !j->annotations.empty();
908 : }
909 4019 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
910 1049 : j(ent2->getDirectOptionalBaseInterfaces().begin());
911 3925 : !ann && j != ent2->getDirectOptionalBaseInterfaces().end();
912 : ++j)
913 : {
914 275 : ann = !j->annotations.empty();
915 : }
916 12024 : for (std::vector<
917 : unoidl::AccumulationBasedServiceEntity::Property >::
918 : const_iterator j(
919 1049 : ent2->getDirectProperties().begin());
920 11904 : !ann && j != ent2->getDirectProperties().end(); ++j)
921 : {
922 2939 : ann = !j->annotations.empty();
923 : }
924 1049 : i->second.dataOffset = getOffset(file);
925 1049 : writeKind(file, ent2.get(), ann);
926 1049 : write32(file, ent2->getDirectMandatoryBaseServices().size());
927 5355 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
928 1049 : j(ent2->getDirectMandatoryBaseServices().begin());
929 3570 : j != ent2->getDirectMandatoryBaseServices().end(); ++j)
930 : {
931 736 : writeIdxName(file, j->name);
932 736 : writeAnnotations(file, ann, j->annotations);
933 : }
934 1049 : write32(file, ent2->getDirectOptionalBaseServices().size());
935 3333 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
936 1049 : j(ent2->getDirectOptionalBaseServices().begin());
937 2222 : j != ent2->getDirectOptionalBaseServices().end(); ++j)
938 : {
939 62 : writeIdxName(file, j->name);
940 62 : writeAnnotations(file, ann, j->annotations);
941 : }
942 1049 : write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
943 7845 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
944 1049 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
945 5230 : j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j)
946 : {
947 1566 : writeIdxName(file, j->name);
948 1566 : writeAnnotations(file, ann, j->annotations);
949 : }
950 1049 : write32(file, ent2->getDirectOptionalBaseInterfaces().size());
951 4029 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
952 1049 : j(ent2->getDirectOptionalBaseInterfaces().begin());
953 2686 : j != ent2->getDirectOptionalBaseInterfaces().end(); ++j)
954 : {
955 294 : writeIdxName(file, j->name);
956 294 : writeAnnotations(file, ann, j->annotations);
957 : }
958 1049 : write32(file, ent2->getDirectProperties().size());
959 12639 : for (std::vector<
960 : unoidl::AccumulationBasedServiceEntity::Property >::
961 : const_iterator j(
962 1049 : ent2->getDirectProperties().begin());
963 8426 : j != ent2->getDirectProperties().end(); ++j)
964 : {
965 3164 : write16(file, static_cast< sal_uInt16 >(j->attributes));
966 3164 : writeIdxName(file, j->name);
967 3164 : writeIdxName(file, j->type);
968 3164 : writeAnnotations(file, ann, j->annotations);
969 : }
970 1049 : writeAnnotations(file, ann, ent2->getAnnotations());
971 1049 : break;
972 : }
973 : case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
974 : {
975 : rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2(
976 : static_cast< unoidl::InterfaceBasedSingletonEntity * >(
977 183 : i->second.entity.get()));
978 183 : bool ann = !ent2->getAnnotations().empty();
979 183 : i->second.dataOffset = getOffset(file);
980 183 : writeKind(file, ent2.get(), ann);
981 183 : writeIdxName(file, ent2->getBase());
982 183 : writeAnnotations(file, ann, ent2->getAnnotations());
983 183 : break;
984 : }
985 : case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
986 : {
987 : rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2(
988 : static_cast< unoidl::ServiceBasedSingletonEntity * >(
989 6 : i->second.entity.get()));
990 6 : bool ann = !ent2->getAnnotations().empty();
991 6 : i->second.dataOffset = getOffset(file);
992 6 : writeKind(file, ent2.get(), ann);
993 6 : writeIdxName(file, ent2->getBase());
994 6 : writeAnnotations(file, ann, ent2->getAnnotations());
995 6 : break;
996 : }
997 : }
998 : }
999 6713 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
1000 : ++i)
1001 : {
1002 6309 : i->second.nameOffset = writeNulName(file, i->first);
1003 : }
1004 404 : sal_uInt64 off = getOffset(file);
1005 404 : if (rootSize == 0) {
1006 250 : write8(file, 0); // SORT_MODULE
1007 250 : write32(file, map.size());
1008 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1009 : } else {
1010 154 : *rootSize = map.size();
1011 : // overflow from std::map::size_type -> std::size_t is unrealistic
1012 : }
1013 6713 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
1014 : ++i)
1015 : {
1016 6309 : write32(file, i->second.nameOffset);
1017 6309 : write32(file, i->second.dataOffset);
1018 : }
1019 404 : return off;
1020 : }
1021 :
1022 : }
1023 :
1024 678 : SAL_IMPLEMENT_MAIN() {
1025 : try {
1026 339 : sal_uInt32 args = rtl_getAppCommandArgCount();
1027 339 : if (args == 0) {
1028 0 : badUsage();
1029 : }
1030 339 : rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
1031 339 : bool entities = false;
1032 678 : rtl::Reference< unoidl::Provider > prov;
1033 678 : std::map< OUString, Item > map;
1034 838 : for (sal_uInt32 i = 0; i != args - 1; ++i) {
1035 : assert(args > 1);
1036 684 : OUString uri(getArgumentUri(i, i == args - 2 ? &entities : 0));
1037 684 : if (entities) {
1038 5 : mapEntities(mgr, uri, map);
1039 : } else {
1040 : try {
1041 679 : prov = mgr->addProvider(uri);
1042 0 : } catch (unoidl::NoSuchFileException &) {
1043 : std::cerr
1044 0 : << "Input <" << uri << "> does not exist" << std::endl;
1045 0 : std::exit(EXIT_FAILURE);
1046 : }
1047 : }
1048 684 : }
1049 154 : if (!entities) {
1050 : mapCursor(
1051 149 : (prov.is()
1052 149 : ? prov->createRootCursor()
1053 : : rtl::Reference< unoidl::MapCursor >()),
1054 298 : map);
1055 : }
1056 308 : osl::File f(getArgumentUri(args - 1, 0));
1057 154 : osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
1058 154 : if (e == osl::FileBase::E_NOENT) {
1059 11 : e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
1060 : }
1061 154 : if (e != osl::FileBase::E_None) {
1062 : std::cerr
1063 0 : << "Cannot open <" << f.getURL() << "> for writing, error code "
1064 0 : << +e << std::endl;
1065 0 : std::exit(EXIT_FAILURE);
1066 : }
1067 154 : write(f, "UNOIDL\xFF\0", 8);
1068 154 : write32(f, 0); // root map offset
1069 154 : write32(f, 0); // root map size
1070 : write(
1071 : f,
1072 154 : RTL_CONSTASCII_STRINGPARAM(
1073 : "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
1074 154 : " unoidl-write **\0"));
1075 : std::size_t size;
1076 154 : sal_uInt64 off = writeMap(f, map, &size);
1077 154 : e = f.setSize(getOffset(f)); // truncate in case it already existed
1078 154 : if (e != osl::FileBase::E_None) {
1079 : std::cerr
1080 0 : << "Cannot set size of <" << f.getURL() << ">, error code "
1081 0 : << +e << std::endl;
1082 0 : std::exit(EXIT_FAILURE);
1083 : }
1084 154 : e = f.setPos(osl_Pos_Absolut, 8);
1085 154 : if (e != osl::FileBase::E_None) {
1086 : std::cerr
1087 0 : << "Cannot rewind current position in <" << f.getURL()
1088 0 : << ">, error code " << +e << std::endl;
1089 0 : std::exit(EXIT_FAILURE);
1090 : }
1091 154 : write32(f, off);
1092 154 : write32(f, size);
1093 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1094 154 : e = f.close();
1095 154 : if (e != osl::FileBase::E_None) {
1096 : std::cerr
1097 0 : << "Cannot close <" << f.getURL()
1098 0 : << "> after writing, error code " << +e << std::endl;
1099 0 : std::exit(EXIT_FAILURE);
1100 : }
1101 493 : return EXIT_SUCCESS;
1102 0 : } catch (unoidl::FileFormatException & e1) {
1103 : std::cerr
1104 370 : << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1105 185 : << std::endl;
1106 185 : std::exit(EXIT_FAILURE);
1107 : }
1108 1017 : }
1109 :
1110 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|