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 0 : OUString getArgumentUri(sal_uInt32 argument, bool * entities) {
58 0 : OUString arg;
59 0 : rtl_getAppCommandArg(argument, &arg.pData);
60 0 : if (arg.startsWith("@", &arg)) {
61 0 : if (entities == 0) {
62 0 : badUsage();
63 : }
64 0 : *entities = true;
65 0 : } else if (entities != 0) {
66 0 : *entities = false;
67 : }
68 0 : OUString url;
69 0 : osl::FileBase::RC e1 = osl::FileBase::getFileURLFromSystemPath(arg, url);
70 0 : 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 0 : OUString cwd;
77 0 : oslProcessError e2 = osl_getProcessWorkingDir(&cwd.pData);
78 0 : 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 0 : OUString abs;
85 0 : e1 = osl::FileBase::getAbsoluteFileURL(cwd, url, abs);
86 0 : 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 0 : return abs;
93 : }
94 :
95 0 : sal_uInt64 getOffset(osl::File & file) {
96 : sal_uInt64 off;
97 0 : osl::FileBase::RC e = file.getPos(off);
98 0 : 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 0 : return off;
105 : }
106 :
107 0 : void write(osl::File & file, void const * buffer, sal_uInt64 size) {
108 : sal_uInt64 n;
109 0 : osl::FileBase::RC e = file.write(buffer, size, n);
110 0 : 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 0 : 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 0 : }
123 :
124 0 : void write8(osl::File & file, sal_uInt64 value) {
125 0 : 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 0 : buf[0] = value & 0xFF;
132 0 : write(file, buf, SAL_N_ELEMENTS(buf));
133 0 : }
134 :
135 0 : void write16(osl::File & file, sal_uInt64 value) {
136 0 : 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 0 : buf[0] = value & 0xFF;
143 0 : buf[1] = (value >> 8) & 0xFF;
144 0 : write(file, buf, SAL_N_ELEMENTS(buf));
145 0 : }
146 :
147 0 : void write32(osl::File & file, sal_uInt64 value) {
148 0 : 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 0 : buf[0] = value & 0xFF;
155 0 : buf[1] = (value >> 8) & 0xFF;
156 0 : buf[2] = (value >> 16) & 0xFF;
157 0 : buf[3] = (value >> 24) & 0xFF;
158 0 : write(file, buf, SAL_N_ELEMENTS(buf));
159 0 : }
160 :
161 0 : void write64(osl::File & file, sal_uInt64 value) {
162 : unsigned char buf[8];
163 0 : buf[0] = value & 0xFF;
164 0 : buf[1] = (value >> 8) & 0xFF;
165 0 : buf[2] = (value >> 16) & 0xFF;
166 0 : buf[3] = (value >> 24) & 0xFF;
167 0 : buf[4] = (value >> 32) & 0xFF;
168 0 : buf[5] = (value >> 40) & 0xFF;
169 0 : buf[6] = (value >> 48) & 0xFF;
170 0 : buf[7] = (value >> 56) & 0xFF;
171 0 : write(file, buf, SAL_N_ELEMENTS(buf));
172 0 : }
173 :
174 0 : 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 0 : 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 0 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
185 0 : }
186 :
187 0 : 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 0 : 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 0 : write(file, sa.buf, SAL_N_ELEMENTS(sa.buf));
200 0 : }
201 :
202 0 : OString toAscii(OUString const & name) {
203 0 : OString ascii;
204 0 : if (!name.convertToString(
205 : &ascii, RTL_TEXTENCODING_ASCII_US,
206 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
207 0 : | 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 0 : return ascii;
214 : }
215 :
216 0 : OString toUtf8(OUString const & string) {
217 0 : OString ascii;
218 0 : if (!string.convertToString(
219 : &ascii, RTL_TEXTENCODING_UTF8,
220 : (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
221 0 : | 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 0 : return ascii;
228 : }
229 :
230 0 : sal_uInt64 writeNulName(osl::File & file, OUString const & name) {
231 0 : OString ascii(toAscii(name));
232 0 : 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 0 : sal_uInt64 off = getOffset(file);
238 0 : write(file, ascii.getStr(), ascii.getLength() + 1);
239 0 : return off;
240 : }
241 :
242 0 : void writeIdxString(osl::File & file, OString const & string) {
243 0 : static std::map< OString, sal_uInt64 > reuse;
244 0 : std::map< OString, sal_uInt64 >::iterator i(reuse.find(string));
245 0 : if (i == reuse.end()) {
246 0 : reuse.insert(std::make_pair(string, getOffset(file)));
247 : assert(
248 : (static_cast< sal_uInt64 >(string.getLength()) & 0x80000000) == 0);
249 0 : write32(file, static_cast< sal_uInt64 >(string.getLength()));
250 0 : write(file, string.getStr(), string.getLength());
251 : } else {
252 0 : 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 0 : write32(file, i->second | 0x80000000);
259 : }
260 0 : }
261 :
262 0 : void writeIdxName(osl::File & file, OUString const & name) {
263 0 : writeIdxString(file, toAscii(name));
264 0 : }
265 :
266 0 : void writeAnnotations(
267 : osl::File & file, bool annotate,
268 : std::vector< OUString > const & annotations)
269 : {
270 : assert(annotate || annotations.empty());
271 0 : if (annotate) {
272 0 : write32(file, annotations.size());
273 : // overflow from std::vector::size_type -> sal_uInt64 is unrealistic
274 0 : for (std::vector< OUString >::const_iterator i(annotations.begin());
275 0 : i != annotations.end(); ++i)
276 : {
277 0 : writeIdxString(file, toUtf8(*i));
278 : }
279 : }
280 0 : }
281 :
282 0 : 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 0 : sal_uInt64 v = entity->getSort();
289 0 : if (entity->isPublished()) {
290 0 : v |= 0x80;
291 : }
292 0 : if (annotated) {
293 0 : v |= 0x40;
294 : }
295 0 : if (flag) {
296 0 : v |= 0x20;
297 : }
298 0 : write8(file, v);
299 0 : }
300 :
301 0 : struct Item {
302 0 : explicit Item(rtl::Reference< unoidl::Entity > const & theEntity):
303 0 : entity(theEntity), nameOffset(0), dataOffset(0)
304 0 : {}
305 :
306 : rtl::Reference< unoidl::Entity > entity;
307 : std::map< OUString, Item > module;
308 : sal_uInt64 nameOffset;
309 : sal_uInt64 dataOffset;
310 : };
311 :
312 0 : struct ConstItem {
313 0 : ConstItem(
314 : unoidl::ConstantValue const & theConstant,
315 : std::vector< OUString > const & theAnnotations):
316 : constant(theConstant), annotations(theAnnotations), nameOffset(0),
317 0 : dataOffset(0)
318 0 : {}
319 :
320 : unoidl::ConstantValue constant;
321 : std::vector< OUString > annotations;
322 : sal_uInt64 nameOffset;
323 : sal_uInt64 dataOffset;
324 : };
325 :
326 0 : void mapEntities(
327 : rtl::Reference< unoidl::Manager > const & manager, OUString const & uri,
328 : std::map< OUString, Item > & map)
329 : {
330 : assert(manager.is());
331 0 : osl::File f(uri);
332 0 : osl::FileBase::RC e = f.open(osl_File_OpenFlag_Read);
333 0 : 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 0 : e = f.isEndOfFile(&eof);
342 0 : 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 0 : if (eof) {
349 0 : break;
350 : }
351 0 : rtl::ByteSequence s1;
352 0 : e = f.readLine(s1);
353 0 : 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 0 : OUString s2;
360 0 : if (!rtl_convertStringToUString(
361 0 : &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 0 : | 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 0 : for (sal_Int32 i = 0; i != -1;) {
373 0 : OUString t(s2.getToken(0, ' ', i));
374 0 : if (!t.isEmpty()) {
375 0 : rtl::Reference< unoidl::Entity > ent(manager->findEntity(t));
376 0 : 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 0 : 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 0 : std::map< OUString, Item > * map2 = ↦
389 0 : for (sal_Int32 j = 0;;) {
390 0 : OUString id(t.getToken(0, '.', j));
391 0 : if (j == -1) {
392 0 : map2->insert(std::make_pair(id, Item(ent)));
393 0 : break;
394 : }
395 0 : std::map< OUString, Item >::iterator k(map2->find(id));
396 0 : if (k == map2->end()) {
397 : rtl::Reference< unoidl::Entity > ent2(
398 0 : manager->findEntity(t.copy(0, j - 1)));
399 : assert(ent2.is());
400 0 : k = map2->insert(std::make_pair(id, Item(ent2))).first;
401 : }
402 : assert(
403 : k->second.entity->getSort()
404 : == unoidl::Entity::SORT_MODULE);
405 0 : map2 = &k->second.module;
406 0 : }
407 : }
408 0 : }
409 0 : }
410 0 : e = f.close();
411 0 : 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 0 : }
417 0 : }
418 :
419 0 : void mapCursor(
420 : rtl::Reference< unoidl::MapCursor > const & cursor,
421 : std::map< OUString, Item > & map)
422 : {
423 0 : if (cursor.is()) {
424 : for (;;) {
425 0 : OUString name;
426 0 : rtl::Reference< unoidl::Entity > ent(cursor->getNext(&name));
427 0 : if (!ent.is()) {
428 0 : break;
429 : }
430 : std::pair< std::map< OUString, Item >::iterator, bool > i(
431 0 : map.insert(std::make_pair(name, Item(ent))));
432 0 : if (!i.second) {
433 0 : std::cout << "Duplicate name \"" << name << '"' << std::endl;
434 0 : std::exit(EXIT_FAILURE);
435 : }
436 0 : 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 0 : i.first->second.entity.get()))->createCursor(),
443 0 : i.first->second.module);
444 : }
445 0 : }
446 : }
447 0 : }
448 :
449 0 : sal_uInt64 writeMap(
450 : osl::File & file, std::map< OUString, Item > & map, std::size_t * rootSize)
451 : {
452 0 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
453 : ++i)
454 : {
455 0 : switch (i->second.entity->getSort()) {
456 : case unoidl::Entity::SORT_MODULE:
457 0 : i->second.dataOffset = writeMap(file, i->second.module, 0);
458 0 : break;
459 : case unoidl::Entity::SORT_ENUM_TYPE:
460 : {
461 : rtl::Reference< unoidl::EnumTypeEntity > ent2(
462 : static_cast< unoidl::EnumTypeEntity * >(
463 0 : i->second.entity.get()));
464 0 : bool ann = !ent2->getAnnotations().empty();
465 0 : for (std::vector< unoidl::EnumTypeEntity::Member >::
466 0 : const_iterator j(ent2->getMembers().begin());
467 0 : !ann && j != ent2->getMembers().end(); ++j)
468 : {
469 0 : ann = !j->annotations.empty();
470 : }
471 0 : i->second.dataOffset = getOffset(file);
472 0 : writeKind(file, ent2.get(), ann);
473 0 : write32(file, ent2->getMembers().size());
474 0 : for (std::vector< unoidl::EnumTypeEntity::Member >::
475 0 : const_iterator j(ent2->getMembers().begin());
476 0 : j != ent2->getMembers().end(); ++j)
477 : {
478 0 : writeIdxName(file, j->name);
479 0 : write32(file, static_cast< sal_uInt32 >(j->value));
480 0 : writeAnnotations(file, ann, j->annotations);
481 : }
482 0 : writeAnnotations(file, ann, ent2->getAnnotations());
483 0 : break;
484 : }
485 : case unoidl::Entity::SORT_PLAIN_STRUCT_TYPE:
486 : {
487 : rtl::Reference< unoidl::PlainStructTypeEntity > ent2(
488 : static_cast< unoidl::PlainStructTypeEntity * >(
489 0 : i->second.entity.get()));
490 0 : bool ann = !ent2->getAnnotations().empty();
491 0 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
492 0 : const_iterator j(ent2->getDirectMembers().begin());
493 0 : !ann && j != ent2->getDirectMembers().end(); ++j)
494 : {
495 0 : ann = !j->annotations.empty();
496 : }
497 0 : i->second.dataOffset = getOffset(file);
498 : writeKind(
499 0 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
500 0 : if (!ent2->getDirectBase().isEmpty()) {
501 0 : writeIdxName(file, ent2->getDirectBase());
502 : }
503 0 : write32(file, ent2->getDirectMembers().size());
504 0 : for (std::vector< unoidl::PlainStructTypeEntity::Member >::
505 0 : const_iterator j(ent2->getDirectMembers().begin());
506 0 : j != ent2->getDirectMembers().end(); ++j)
507 : {
508 0 : writeIdxName(file, j->name);
509 0 : writeIdxName(file, j->type);
510 0 : writeAnnotations(file, ann, j->annotations);
511 : }
512 0 : writeAnnotations(file, ann, ent2->getAnnotations());
513 0 : 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 0 : i->second.entity.get()));
522 0 : bool ann = !ent2->getAnnotations().empty();
523 0 : for (std::vector<
524 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
525 : const_iterator j(
526 0 : ent2->getMembers().begin());
527 0 : !ann && j != ent2->getMembers().end(); ++j)
528 : {
529 0 : ann = !j->annotations.empty();
530 : }
531 0 : i->second.dataOffset = getOffset(file);
532 0 : writeKind(file, ent2.get(), ann);
533 0 : write32(file, ent2->getTypeParameters().size());
534 0 : for (std::vector< OUString >::const_iterator j(
535 0 : ent2->getTypeParameters().begin());
536 0 : j != ent2->getTypeParameters().end(); ++j)
537 : {
538 0 : writeIdxName(file, *j);
539 : }
540 0 : write32(file, ent2->getMembers().size());
541 0 : for (std::vector<
542 : unoidl::PolymorphicStructTypeTemplateEntity::Member >::
543 : const_iterator j(
544 0 : ent2->getMembers().begin());
545 0 : j != ent2->getMembers().end(); ++j)
546 : {
547 0 : sal_uInt64 f = 0;
548 0 : if (j->parameterized) {
549 0 : f |= 0x01;
550 : }
551 0 : write8(file, f);
552 0 : writeIdxName(file, j->name);
553 0 : writeIdxName(file, j->type);
554 0 : writeAnnotations(file, ann, j->annotations);
555 : }
556 0 : writeAnnotations(file, ann, ent2->getAnnotations());
557 0 : break;
558 : }
559 : case unoidl::Entity::SORT_EXCEPTION_TYPE:
560 : {
561 : rtl::Reference< unoidl::ExceptionTypeEntity > ent2(
562 : static_cast< unoidl::ExceptionTypeEntity * >(
563 0 : i->second.entity.get()));
564 0 : bool ann = !ent2->getAnnotations().empty();
565 0 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
566 0 : const_iterator j(ent2->getDirectMembers().begin());
567 0 : !ann && j != ent2->getDirectMembers().end(); ++j)
568 : {
569 0 : ann = !j->annotations.empty();
570 : }
571 0 : i->second.dataOffset = getOffset(file);
572 : writeKind(
573 0 : file, ent2.get(), ann, !ent2->getDirectBase().isEmpty());
574 0 : if (!ent2->getDirectBase().isEmpty()) {
575 0 : writeIdxName(file, ent2->getDirectBase());
576 : }
577 0 : write32(file, ent2->getDirectMembers().size());
578 0 : for (std::vector< unoidl::ExceptionTypeEntity::Member >::
579 0 : const_iterator j(ent2->getDirectMembers().begin());
580 0 : j != ent2->getDirectMembers().end(); ++j)
581 : {
582 0 : writeIdxName(file, j->name);
583 0 : writeIdxName(file, j->type);
584 0 : writeAnnotations(file, ann, j->annotations);
585 : }
586 0 : writeAnnotations(file, ann, ent2->getAnnotations());
587 0 : break;
588 : }
589 : case unoidl::Entity::SORT_INTERFACE_TYPE:
590 : {
591 : rtl::Reference< unoidl::InterfaceTypeEntity > ent2(
592 : static_cast< unoidl::InterfaceTypeEntity * >(
593 0 : i->second.entity.get()));
594 0 : bool ann = !ent2->getAnnotations().empty();
595 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
596 0 : j(ent2->getDirectMandatoryBases().begin());
597 0 : !ann && j != ent2->getDirectMandatoryBases().end(); ++j)
598 : {
599 0 : ann = !j->annotations.empty();
600 : }
601 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
602 0 : j(ent2->getDirectOptionalBases().begin());
603 0 : !ann && j != ent2->getDirectOptionalBases().end(); ++j)
604 : {
605 0 : ann = !j->annotations.empty();
606 : }
607 0 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
608 0 : const_iterator j(ent2->getDirectAttributes().begin());
609 0 : !ann && j != ent2->getDirectAttributes().end(); ++j)
610 : {
611 0 : ann = !j->annotations.empty();
612 : }
613 0 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
614 0 : const_iterator j(ent2->getDirectMethods().begin());
615 0 : !ann && j != ent2->getDirectMethods().end(); ++j)
616 : {
617 0 : ann = !j->annotations.empty();
618 : }
619 0 : i->second.dataOffset = getOffset(file);
620 0 : writeKind(file, ent2.get(), ann);
621 0 : write32(file, ent2->getDirectMandatoryBases().size());
622 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
623 0 : j(ent2->getDirectMandatoryBases().begin());
624 0 : j != ent2->getDirectMandatoryBases().end(); ++j)
625 : {
626 0 : writeIdxName(file, j->name);
627 0 : writeAnnotations(file, ann, j->annotations);
628 : }
629 0 : write32(file, ent2->getDirectOptionalBases().size());
630 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
631 0 : j(ent2->getDirectOptionalBases().begin());
632 0 : j != ent2->getDirectOptionalBases().end(); ++j)
633 : {
634 0 : writeIdxName(file, j->name);
635 0 : writeAnnotations(file, ann, j->annotations);
636 : }
637 0 : write32(file, ent2->getDirectAttributes().size());
638 0 : for (std::vector< unoidl::InterfaceTypeEntity::Attribute >::
639 0 : const_iterator j(ent2->getDirectAttributes().begin());
640 0 : j != ent2->getDirectAttributes().end(); ++j)
641 : {
642 0 : sal_uInt64 f = 0;
643 0 : if (j->bound) {
644 0 : f |= 0x01;
645 : }
646 0 : if (j->readOnly) {
647 0 : f |= 0x02;
648 : }
649 0 : write8(file, f);
650 0 : writeIdxName(file, j->name);
651 0 : writeIdxName(file, j->type);
652 0 : write32(file, j->getExceptions.size());
653 0 : for (std::vector< OUString >::const_iterator k(
654 0 : j->getExceptions.begin());
655 0 : k != j->getExceptions.end(); ++k)
656 : {
657 0 : writeIdxName(file, *k);
658 : }
659 0 : if (!j->readOnly) {
660 0 : write32(file, j->setExceptions.size());
661 0 : for (std::vector< OUString >::const_iterator k(
662 0 : j->setExceptions.begin());
663 0 : k != j->setExceptions.end(); ++k)
664 : {
665 0 : writeIdxName(file, *k);
666 : }
667 : }
668 0 : writeAnnotations(file, ann, j->annotations);
669 : }
670 0 : write32(file, ent2->getDirectMethods().size());
671 0 : for (std::vector< unoidl::InterfaceTypeEntity::Method >::
672 0 : const_iterator j(ent2->getDirectMethods().begin());
673 0 : j != ent2->getDirectMethods().end(); ++j)
674 : {
675 0 : writeIdxName(file, j->name);
676 0 : writeIdxName(file, j->returnType);
677 0 : write32(file, j->parameters.size());
678 0 : for (std::vector<
679 : unoidl::InterfaceTypeEntity::Method::Parameter >::
680 0 : const_iterator k(j->parameters.begin());
681 0 : k != j->parameters.end(); ++k)
682 : {
683 0 : write8(file, k->direction);
684 0 : writeIdxName(file, k->name);
685 0 : writeIdxName(file, k->type);
686 : }
687 0 : write32(file, j->exceptions.size());
688 0 : for (std::vector< OUString >::const_iterator k(
689 0 : j->exceptions.begin());
690 0 : k != j->exceptions.end(); ++k)
691 : {
692 0 : writeIdxName(file, *k);
693 : }
694 0 : writeAnnotations(file, ann, j->annotations);
695 : }
696 0 : writeAnnotations(file, ann, ent2->getAnnotations());
697 0 : break;
698 : }
699 : case unoidl::Entity::SORT_TYPEDEF:
700 : {
701 : rtl::Reference< unoidl::TypedefEntity > ent2(
702 : static_cast< unoidl::TypedefEntity * >(
703 0 : i->second.entity.get()));
704 0 : bool ann = !ent2->getAnnotations().empty();
705 0 : i->second.dataOffset = getOffset(file);
706 0 : writeKind(file, ent2.get(), ann);
707 0 : writeIdxName(file, ent2->getType());
708 0 : writeAnnotations(file, ann, ent2->getAnnotations());
709 0 : break;
710 : }
711 : case unoidl::Entity::SORT_CONSTANT_GROUP:
712 : {
713 : rtl::Reference< unoidl::ConstantGroupEntity > ent2(
714 : static_cast< unoidl::ConstantGroupEntity * >(
715 0 : i->second.entity.get()));
716 0 : std::map< OUString, ConstItem > cmap;
717 0 : for (std::vector< unoidl::ConstantGroupEntity::Member >::
718 0 : const_iterator j(ent2->getMembers().begin());
719 0 : j != ent2->getMembers().end(); ++j)
720 : {
721 0 : if (!cmap.insert(
722 : std::make_pair(
723 0 : j->name, ConstItem(j->value, j->annotations))).
724 0 : 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 0 : for (std::map< OUString, ConstItem >::iterator j(cmap.begin());
733 0 : j != cmap.end(); ++j)
734 : {
735 0 : j->second.dataOffset = getOffset(file);
736 0 : sal_uInt64 v = j->second.constant.type;
737 0 : if (!j->second.annotations.empty()) {
738 0 : v |= 0x80;
739 : }
740 0 : write8(file, v);
741 0 : switch (j->second.constant.type) {
742 : case unoidl::ConstantValue::TYPE_BOOLEAN:
743 0 : write8(file, j->second.constant.booleanValue ? 1 : 0);
744 0 : break;
745 : case unoidl::ConstantValue::TYPE_BYTE:
746 : write8(
747 : file,
748 : static_cast< sal_uInt8 >(
749 0 : j->second.constant.byteValue));
750 0 : break;
751 : case unoidl::ConstantValue::TYPE_SHORT:
752 : write16(
753 : file,
754 : static_cast< sal_uInt16 >(
755 0 : j->second.constant.shortValue));
756 0 : break;
757 : case unoidl::ConstantValue::TYPE_UNSIGNED_SHORT:
758 0 : write16(file, j->second.constant.unsignedShortValue);
759 0 : break;
760 : case unoidl::ConstantValue::TYPE_LONG:
761 : write32(
762 : file,
763 : static_cast< sal_uInt32 >(
764 0 : j->second.constant.longValue));
765 0 : break;
766 : case unoidl::ConstantValue::TYPE_UNSIGNED_LONG:
767 0 : write32(file, j->second.constant.unsignedLongValue);
768 0 : break;
769 : case unoidl::ConstantValue::TYPE_HYPER:
770 : write64(
771 : file,
772 : static_cast< sal_uInt64 >(
773 0 : j->second.constant.hyperValue));
774 0 : break;
775 : case unoidl::ConstantValue::TYPE_UNSIGNED_HYPER:
776 0 : write64(file, j->second.constant.unsignedHyperValue);
777 0 : break;
778 : case unoidl::ConstantValue::TYPE_FLOAT:
779 : writeIso60599Binary32(
780 0 : file, j->second.constant.floatValue);
781 0 : break;
782 : case unoidl::ConstantValue::TYPE_DOUBLE:
783 : writeIso60599Binary64(
784 0 : file, j->second.constant.doubleValue);
785 0 : break;
786 : default:
787 0 : for (;;) { std::abort(); } // this cannot happen
788 : }
789 : writeAnnotations(
790 0 : file, !j->second.annotations.empty(),
791 0 : j->second.annotations);
792 : }
793 0 : for (std::map< OUString, ConstItem >::iterator j(
794 0 : cmap.begin());
795 0 : j != cmap.end(); ++j)
796 : {
797 0 : j->second.nameOffset = writeNulName(file, j->first);
798 : }
799 0 : bool ann = !ent2->getAnnotations().empty();
800 0 : i->second.dataOffset = getOffset(file);
801 0 : writeKind(file, ent2.get(), ann);
802 0 : write32(file, cmap.size());
803 : // overflow from std::map::size_type -> sal_uInt64 is
804 : // unrealistic
805 0 : for (std::map< OUString, ConstItem >::iterator j(
806 0 : cmap.begin());
807 0 : j != cmap.end(); ++j)
808 : {
809 0 : write32(file, j->second.nameOffset);
810 0 : write32(file, j->second.dataOffset);
811 : }
812 0 : writeAnnotations(file, ann, ent2->getAnnotations());
813 0 : 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 0 : i->second.entity.get()));
822 0 : bool dfltCtor = ent2->getConstructors().size() == 1
823 0 : && ent2->getConstructors()[0].defaultConstructor;
824 0 : bool ann = !ent2->getAnnotations().empty();
825 0 : if (!dfltCtor) {
826 0 : for (std::vector<
827 : unoidl::SingleInterfaceBasedServiceEntity::
828 : Constructor >::const_iterator j(
829 0 : ent2->getConstructors().begin());
830 0 : !ann && j != ent2->getConstructors().end(); ++j)
831 : {
832 0 : ann = !j->annotations.empty();
833 : }
834 : }
835 0 : i->second.dataOffset = getOffset(file);
836 0 : writeKind(file, ent2.get(), ann, dfltCtor);
837 0 : writeIdxName(file, ent2->getBase());
838 0 : if (!dfltCtor) {
839 0 : write32(file, ent2->getConstructors().size());
840 0 : for (std::vector<
841 : unoidl::SingleInterfaceBasedServiceEntity::
842 : Constructor >::const_iterator j(
843 0 : ent2->getConstructors().begin());
844 0 : j != ent2->getConstructors().end(); ++j)
845 : {
846 0 : 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 0 : writeIdxName(file, j->name);
853 0 : write32(file, j->parameters.size());
854 0 : for (std::vector<
855 : unoidl::SingleInterfaceBasedServiceEntity::
856 : Constructor::Parameter >::const_iterator k(
857 0 : j->parameters.begin());
858 0 : k != j->parameters.end(); ++k)
859 : {
860 0 : sal_uInt64 f = 0;
861 0 : if (k->rest) {
862 0 : f |= 0x04;
863 : }
864 0 : write8(file, f);
865 0 : writeIdxName(file, k->name);
866 0 : writeIdxName(file, k->type);
867 : }
868 0 : write32(file, j->exceptions.size());
869 0 : for (std::vector< OUString >::const_iterator k(
870 0 : j->exceptions.begin());
871 0 : k != j->exceptions.end(); ++k)
872 : {
873 0 : writeIdxName(file, *k);
874 : }
875 0 : writeAnnotations(file, ann, j->annotations);
876 : }
877 : }
878 0 : writeAnnotations(file, ann, ent2->getAnnotations());
879 0 : break;
880 : }
881 : case unoidl::Entity::SORT_ACCUMULATION_BASED_SERVICE:
882 : {
883 : rtl::Reference< unoidl::AccumulationBasedServiceEntity > ent2(
884 : static_cast< unoidl::AccumulationBasedServiceEntity * >(
885 0 : i->second.entity.get()));
886 0 : bool ann = !ent2->getAnnotations().empty();
887 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
888 0 : j(ent2->getDirectMandatoryBaseServices().begin());
889 0 : !ann && j != ent2->getDirectMandatoryBaseServices().end();
890 : ++j)
891 : {
892 0 : ann = !j->annotations.empty();
893 : }
894 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
895 0 : j(ent2->getDirectOptionalBaseServices().begin());
896 0 : !ann && j != ent2->getDirectOptionalBaseServices().end();
897 : ++j)
898 : {
899 0 : ann = !j->annotations.empty();
900 : }
901 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
902 0 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
903 0 : (!ann
904 0 : && j != ent2->getDirectMandatoryBaseInterfaces().end());
905 : ++j)
906 : {
907 0 : ann = !j->annotations.empty();
908 : }
909 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
910 0 : j(ent2->getDirectOptionalBaseInterfaces().begin());
911 0 : !ann && j != ent2->getDirectOptionalBaseInterfaces().end();
912 : ++j)
913 : {
914 0 : ann = !j->annotations.empty();
915 : }
916 0 : for (std::vector<
917 : unoidl::AccumulationBasedServiceEntity::Property >::
918 : const_iterator j(
919 0 : ent2->getDirectProperties().begin());
920 0 : !ann && j != ent2->getDirectProperties().end(); ++j)
921 : {
922 0 : ann = !j->annotations.empty();
923 : }
924 0 : i->second.dataOffset = getOffset(file);
925 0 : writeKind(file, ent2.get(), ann);
926 0 : write32(file, ent2->getDirectMandatoryBaseServices().size());
927 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
928 0 : j(ent2->getDirectMandatoryBaseServices().begin());
929 0 : j != ent2->getDirectMandatoryBaseServices().end(); ++j)
930 : {
931 0 : writeIdxName(file, j->name);
932 0 : writeAnnotations(file, ann, j->annotations);
933 : }
934 0 : write32(file, ent2->getDirectOptionalBaseServices().size());
935 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
936 0 : j(ent2->getDirectOptionalBaseServices().begin());
937 0 : j != ent2->getDirectOptionalBaseServices().end(); ++j)
938 : {
939 0 : writeIdxName(file, j->name);
940 0 : writeAnnotations(file, ann, j->annotations);
941 : }
942 0 : write32(file, ent2->getDirectMandatoryBaseInterfaces().size());
943 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
944 0 : j(ent2->getDirectMandatoryBaseInterfaces().begin());
945 0 : j != ent2->getDirectMandatoryBaseInterfaces().end(); ++j)
946 : {
947 0 : writeIdxName(file, j->name);
948 0 : writeAnnotations(file, ann, j->annotations);
949 : }
950 0 : write32(file, ent2->getDirectOptionalBaseInterfaces().size());
951 0 : for (std::vector< unoidl::AnnotatedReference >::const_iterator
952 0 : j(ent2->getDirectOptionalBaseInterfaces().begin());
953 0 : j != ent2->getDirectOptionalBaseInterfaces().end(); ++j)
954 : {
955 0 : writeIdxName(file, j->name);
956 0 : writeAnnotations(file, ann, j->annotations);
957 : }
958 0 : write32(file, ent2->getDirectProperties().size());
959 0 : for (std::vector<
960 : unoidl::AccumulationBasedServiceEntity::Property >::
961 : const_iterator j(
962 0 : ent2->getDirectProperties().begin());
963 0 : j != ent2->getDirectProperties().end(); ++j)
964 : {
965 0 : write16(file, static_cast< sal_uInt16 >(j->attributes));
966 0 : writeIdxName(file, j->name);
967 0 : writeIdxName(file, j->type);
968 0 : writeAnnotations(file, ann, j->annotations);
969 : }
970 0 : writeAnnotations(file, ann, ent2->getAnnotations());
971 0 : break;
972 : }
973 : case unoidl::Entity::SORT_INTERFACE_BASED_SINGLETON:
974 : {
975 : rtl::Reference< unoidl::InterfaceBasedSingletonEntity > ent2(
976 : static_cast< unoidl::InterfaceBasedSingletonEntity * >(
977 0 : i->second.entity.get()));
978 0 : bool ann = !ent2->getAnnotations().empty();
979 0 : i->second.dataOffset = getOffset(file);
980 0 : writeKind(file, ent2.get(), ann);
981 0 : writeIdxName(file, ent2->getBase());
982 0 : writeAnnotations(file, ann, ent2->getAnnotations());
983 0 : break;
984 : }
985 : case unoidl::Entity::SORT_SERVICE_BASED_SINGLETON:
986 : {
987 : rtl::Reference< unoidl::ServiceBasedSingletonEntity > ent2(
988 : static_cast< unoidl::ServiceBasedSingletonEntity * >(
989 0 : i->second.entity.get()));
990 0 : bool ann = !ent2->getAnnotations().empty();
991 0 : i->second.dataOffset = getOffset(file);
992 0 : writeKind(file, ent2.get(), ann);
993 0 : writeIdxName(file, ent2->getBase());
994 0 : writeAnnotations(file, ann, ent2->getAnnotations());
995 0 : break;
996 : }
997 : }
998 : }
999 0 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
1000 : ++i)
1001 : {
1002 0 : i->second.nameOffset = writeNulName(file, i->first);
1003 : }
1004 0 : sal_uInt64 off = getOffset(file);
1005 0 : if (rootSize == 0) {
1006 0 : write8(file, 0); // SORT_MODULE
1007 0 : write32(file, map.size());
1008 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1009 : } else {
1010 0 : *rootSize = map.size();
1011 : // overflow from std::map::size_type -> std::size_t is unrealistic
1012 : }
1013 0 : for (std::map< OUString, Item >::iterator i(map.begin()); i != map.end();
1014 : ++i)
1015 : {
1016 0 : write32(file, i->second.nameOffset);
1017 0 : write32(file, i->second.dataOffset);
1018 : }
1019 0 : return off;
1020 : }
1021 :
1022 : }
1023 :
1024 0 : SAL_IMPLEMENT_MAIN() {
1025 : try {
1026 0 : sal_uInt32 args = rtl_getAppCommandArgCount();
1027 0 : if (args == 0) {
1028 0 : badUsage();
1029 : }
1030 0 : rtl::Reference< unoidl::Manager > mgr(new unoidl::Manager);
1031 0 : bool entities = false;
1032 0 : rtl::Reference< unoidl::Provider > prov;
1033 0 : std::map< OUString, Item > map;
1034 0 : for (sal_uInt32 i = 0; i != args - 1; ++i) {
1035 : assert(args > 1);
1036 0 : OUString uri(getArgumentUri(i, i == args - 2 ? &entities : 0));
1037 0 : if (entities) {
1038 0 : mapEntities(mgr, uri, map);
1039 : } else {
1040 : try {
1041 0 : prov = unoidl::loadProvider(mgr, 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 0 : mgr->addProvider(prov);
1048 : }
1049 0 : }
1050 0 : if (!entities) {
1051 : mapCursor(
1052 0 : (prov.is()
1053 0 : ? prov->createRootCursor()
1054 : : rtl::Reference< unoidl::MapCursor >()),
1055 0 : map);
1056 : }
1057 0 : osl::File f(getArgumentUri(args - 1, 0));
1058 0 : osl::FileBase::RC e = f.open(osl_File_OpenFlag_Write);
1059 0 : if (e == osl::FileBase::E_NOENT) {
1060 0 : e = f.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create);
1061 : }
1062 0 : if (e != osl::FileBase::E_None) {
1063 : std::cerr
1064 0 : << "Cannot open <" << f.getURL() << "> for writing, error code "
1065 0 : << +e << std::endl;
1066 0 : std::exit(EXIT_FAILURE);
1067 : }
1068 0 : write(f, "UNOIDL\xFF\0", 8);
1069 0 : write32(f, 0); // root map offset
1070 0 : write32(f, 0); // root map size
1071 : write(
1072 : f,
1073 0 : RTL_CONSTASCII_STRINGPARAM(
1074 : "\0** Created by LibreOffice " LIBO_VERSION_DOTTED
1075 0 : " unoidl-write **\0"));
1076 : std::size_t size;
1077 0 : sal_uInt64 off = writeMap(f, map, &size);
1078 0 : e = f.setSize(getOffset(f)); // truncate in case it already existed
1079 0 : if (e != osl::FileBase::E_None) {
1080 : std::cerr
1081 0 : << "Cannot set size of <" << f.getURL() << ">, error code "
1082 0 : << +e << std::endl;
1083 0 : std::exit(EXIT_FAILURE);
1084 : }
1085 0 : e = f.setPos(osl_Pos_Absolut, 8);
1086 0 : if (e != osl::FileBase::E_None) {
1087 : std::cerr
1088 0 : << "Cannot rewind current position in <" << f.getURL()
1089 0 : << ">, error code " << +e << std::endl;
1090 0 : std::exit(EXIT_FAILURE);
1091 : }
1092 0 : write32(f, off);
1093 0 : write32(f, size);
1094 : // overflow from std::map::size_type -> sal_uInt64 is unrealistic
1095 0 : e = f.close();
1096 0 : if (e != osl::FileBase::E_None) {
1097 : std::cerr
1098 0 : << "Cannot close <" << f.getURL()
1099 0 : << "> after writing, error code " << +e << std::endl;
1100 0 : std::exit(EXIT_FAILURE);
1101 : }
1102 0 : return EXIT_SUCCESS;
1103 0 : } catch (unoidl::FileFormatException & e1) {
1104 : std::cerr
1105 0 : << "Bad input <" << e1.getUri() << ">: " << e1.getDetail()
1106 0 : << std::endl;
1107 0 : std::exit(EXIT_FAILURE);
1108 : }
1109 0 : }
1110 :
1111 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|