LibreOffice Module cli_ure (master) 1
climaker_app.cxx
Go to the documentation of this file.
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 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include "sal/config.h"
21
22#include <cstdlib>
23#include <iostream>
24#include <stdio.h>
25#include <vector>
26
27#include "climaker_share.h"
28
29#include "sal/main.h"
30#include "osl/process.h"
31#include "osl/file.hxx"
32#include "osl/thread.h"
33#include "rtl/ustrbuf.hxx"
35#include "com/sun/star/lang/XComponent.hpp"
36#include "com/sun/star/container/XHierarchicalNameAccess.hpp"
37#include "com/sun/star/container/XSet.hpp"
38#include "com/sun/star/reflection/XTypeDescriptionEnumerationAccess.hpp"
39#include "com/sun/star/uno/XComponentContext.hpp"
40#include "unoidl/unoidl.hxx"
41
42using namespace ::System::Reflection;
43
44
45using namespace ::osl;
46using namespace ::com::sun::star;
47using namespace ::com::sun::star::uno;
48
49namespace climaker
50{
51
52
53static char const s_usingText [] =
54"\n"
55"using: climaker <switches> [registry-file-1 registry-file-2 ...]\n"
56"\n"
57"switches:\n"
58" -O, --out <output-file> output assembly file;\n"
59" defaults to cli_unotypes.dll if more than one\n"
60" registry-file is given, else <registry-file>.dll\n"
61" -T, --types types to be generated (if none is given,\n"
62" <type1[;type2;...]> then all types of given registries are emitted\n"
63" -X, --extra <rdb-file> additional rdb to saturate referenced types in\n"
64" given registry file(s); these types will not be\n"
65" emitted into the output assembly file\n"
66" -r, --reference reference metadata from assembly file\n"
67" <assembly-file>\n"
68" -k, --keyfile keyfile needed for strong name\n"
69" --assembly-version <version> sets assembly version\n"
70" --assembly-description <text> sets assembly description text\n"
71" --assembly-product <text> sets assembly product name\n"
72" --assembly-company <text> sets assembly company\n"
73" --assembly-copyright <text> sets assembly copyright\n"
74" --assembly-trademark <text> sets assembly trademark\n"
75" -v, --verbose verbose output to stdout\n"
76" -h, --help this message\n"
77"\n"
78"example: climaker --out cli_mytypes.dll \\\n"
79" --reference cli_uretypes.dll \\\n"
80" --extra types.rdb \\\n"
81" mytypes.rdb\n"
82"\n";
83
85{
86 char const * m_name;
87 sal_uInt32 m_name_length;
90};
91
92bool g_bVerbose = false;
93
94
95static const OptionInfo s_option_infos [] = {
96 { RTL_CONSTASCII_STRINGPARAM("out"), 'O', true },
97 { RTL_CONSTASCII_STRINGPARAM("types"), 'T', true },
98 { RTL_CONSTASCII_STRINGPARAM("extra"), 'X', true },
99 { RTL_CONSTASCII_STRINGPARAM("reference"), 'r', true },
100 { RTL_CONSTASCII_STRINGPARAM("keyfile"), 'k', true },
101 { RTL_CONSTASCII_STRINGPARAM("delaySign"), 'd', true },
102 { RTL_CONSTASCII_STRINGPARAM("assembly-version"), '\0', true },
103 { RTL_CONSTASCII_STRINGPARAM("assembly-description"), '\0', true },
104 { RTL_CONSTASCII_STRINGPARAM("assembly-product"), '\0', true },
105 { RTL_CONSTASCII_STRINGPARAM("assembly-company"), '\0', true },
106 { RTL_CONSTASCII_STRINGPARAM("assembly-copyright"), '\0', true },
107 { RTL_CONSTASCII_STRINGPARAM("assembly-trademark"), '\0', true },
108 { RTL_CONSTASCII_STRINGPARAM("verbose"), 'v', false },
109 { RTL_CONSTASCII_STRINGPARAM("help"), 'h', false }
110};
111
112
114 OUString const & opt, sal_Unicode copt = '\0' )
115{
116 for ( sal_Int32 pos = 0;
117 pos < (sizeof (s_option_infos) / sizeof (OptionInfo));
118 ++pos )
119 {
120 OptionInfo const & option_info = s_option_infos[ pos ];
121
122 if (opt.getLength() > 0)
123 {
124 if (opt.equalsAsciiL(
125 option_info.m_name, option_info.m_name_length ) &&
126 (copt == '\0' || copt == option_info.m_short_option))
127 {
128 return &option_info;
129 }
130 }
131 else
132 {
133 OSL_ASSERT( copt != '\0' );
134 if (copt == option_info.m_short_option)
135 {
136 return &option_info;
137 }
138 }
139 }
140 OSL_FAIL(
141 OUStringToOString( opt, osl_getThreadTextEncoding() ).getStr() );
142 return 0;
143}
144
145
146static bool is_option(
147 OptionInfo const * option_info, sal_uInt32 * pIndex )
148{
149 OSL_ASSERT( option_info != 0 );
150 if (osl_getCommandArgCount() <= *pIndex)
151 return false;
152
153 OUString arg;
154 osl_getCommandArg( *pIndex, &arg.pData );
155 sal_Int32 len = arg.getLength();
156
157 if (len < 2 || arg[ 0 ] != '-')
158 return false;
159
160 if (len == 2 && arg[ 1 ] == option_info->m_short_option)
161 {
162 ++(*pIndex);
163 return true;
164 }
165 if (arg[ 1 ] == '-' && rtl_ustr_ascii_compare(
166 arg.pData->buffer + 2, option_info->m_name ) == 0)
167 {
168 ++(*pIndex);
169 return true;
170 }
171 return false;
172}
173
174
175static inline bool read_option(
176 bool * flag, OptionInfo const * option_info, sal_uInt32 * pIndex )
177{
178 bool ret = is_option( option_info, pIndex );
179 if (ret)
180 *flag = true;
181 return ret;
182}
183
184
185static bool read_argument(
186 OUString * pValue, OptionInfo const * option_info, sal_uInt32 * pIndex )
187{
188 if (is_option( option_info, pIndex ))
189 {
190 if (*pIndex < osl_getCommandArgCount())
191 {
192 osl_getCommandArg( *pIndex, &pValue->pData );
193 ++(*pIndex);
194 return true;
195 }
196 --(*pIndex);
197 }
198 return false;
199}
200
201
202static OUString const & path_get_working_dir()
203{
204 static OUString s_workingDir;
205 if (! s_workingDir.getLength())
206 osl_getProcessWorkingDir( &s_workingDir.pData );
207 return s_workingDir;
208}
209
210
211static OUString path_make_absolute_file_url( OUString const & path )
212{
213 OUString file_url;
214 oslFileError rc = osl_getFileURLFromSystemPath(
215 path.pData, &file_url.pData );
216 if (osl_File_E_None == rc)
217 {
218 OUString abs;
219 rc = osl_getAbsoluteFileURL(
220 path_get_working_dir().pData, file_url.pData, &abs.pData );
221 if (osl_File_E_None == rc)
222 {
223 return abs;
224 }
225 else
226 {
227 throw RuntimeException(
228 "cannot make absolute: " + file_url );
229 }
230 }
231 else
232 {
233 throw RuntimeException(
234 "cannot get file url from system path: " + path );
235 }
236}
237
238}
239
240using namespace ::climaker;
241
242
244{
245 sal_uInt32 nCount = osl_getCommandArgCount();
246 if (0 == nCount)
247 {
248 puts( s_usingText );
249 return 0;
250 }
251
252 int ret = 0;
253 css::uno::Reference< XComponentContext > xContext;
254
255 try
256 {
257 OptionInfo const * info_help =
258 get_option_info( "help" );
259 OptionInfo const * info_verbose =
260 get_option_info( "verbose" );
261 OptionInfo const * info_out =
262 get_option_info( "out" );
263 OptionInfo const * info_types =
264 get_option_info( "types" );
265 OptionInfo const * info_reference =
266 get_option_info( "reference" );
267 OptionInfo const * info_extra =
268 get_option_info( "extra" );
269 OptionInfo const * info_keyfile =
270 get_option_info( "keyfile" );
271 OptionInfo const * info_delaySign =
272 get_option_info( "delaySign" );
273 OptionInfo const * info_version =
274 get_option_info( "assembly-version" );
275 OptionInfo const * info_product =
276 get_option_info( "assembly-product" );
277 OptionInfo const * info_description =
278 get_option_info( "assembly-description" );
279 OptionInfo const * info_company =
280 get_option_info( "assembly-company" );
281 OptionInfo const * info_copyright =
282 get_option_info( "assembly-copyright" );
283 OptionInfo const * info_trademark =
284 get_option_info( "assembly-trademark" );
285
286 OUString output;
287 std::vector< OUString > mandatory_registries;
288 std::vector< OUString > extra_registries;
289 std::vector< OUString > extra_assemblies;
290 std::vector< OUString > explicit_types;
291 OUString version, product, description, company, copyright, trademark,
292 keyfile, delaySign;
293
294 OUString cmd_arg;
295 for ( sal_uInt32 nPos = 0; nPos < nCount; )
296 {
297 // options
298 if (is_option( info_help, &nPos ))
299 {
300 puts( s_usingText );
301 return 0;
302 }
303 else if (read_argument( &cmd_arg, info_types, &nPos ))
304 {
305 sal_Int32 index = 0;
306 do
307 {
308 explicit_types.push_back(
309 cmd_arg.getToken( 0, ';', index ) );
310 }
311 while (index >= 0);
312 }
313 else if (read_argument( &cmd_arg, info_extra, &nPos ))
314 {
315 extra_registries.push_back(
316 path_make_absolute_file_url( cmd_arg ) );
317 }
318 else if (read_argument( &cmd_arg, info_reference, &nPos ))
319 {
320 extra_assemblies.push_back(
321 path_make_absolute_file_url( cmd_arg ) );
322 }
323 else if (!read_option( &g_bVerbose, info_verbose, &nPos ) &&
324 !read_argument( &output, info_out, &nPos ) &&
325 !read_argument( &version, info_version, &nPos ) &&
326 !read_argument( &description, info_description, &nPos ) &&
327 !read_argument( &product, info_product, &nPos ) &&
328 !read_argument( &company, info_company, &nPos ) &&
329 !read_argument( &copyright, info_copyright, &nPos ) &&
330 !read_argument( &trademark, info_trademark, &nPos ) &&
331 !read_argument( &keyfile, info_keyfile, &nPos ) &&
332 !read_argument( &delaySign, info_delaySign, &nPos ))
333 {
334 osl_getCommandArg( nPos, &cmd_arg.pData );
335 ++nPos;
336 cmd_arg = cmd_arg.trim();
337 if (cmd_arg.getLength() > 0)
338 {
339 if (cmd_arg[ 0 ] == '-') // is option
340 {
341 OptionInfo const * option_info = 0;
342 if (cmd_arg.getLength() > 2 &&
343 cmd_arg[ 1 ] == '-')
344 {
345 // long option
346 option_info = get_option_info(
347 cmd_arg.copy( 2 ), '\0' );
348 }
349 else if (cmd_arg.getLength() == 2 &&
350 cmd_arg[ 1 ] != '-')
351 {
352 // short option
353 option_info = get_option_info(
354 OUString(), cmd_arg[ 1 ] );
355 }
356 if (option_info == 0)
357 {
358 throw RuntimeException("unknown option " + cmd_arg + "! Use climaker --help to print all options.");
359 }
360 else
361 {
362 OSL_FAIL( "unhandled valid option?!" );
363 if (option_info->m_has_argument)
364 ++nPos;
365 }
366 }
367 else
368 {
369 mandatory_registries.push_back(
370 path_make_absolute_file_url( cmd_arg ) );
371 }
372 }
373 }
374 }
375
376 // bootstrap uno
377 xContext = ::cppu::defaultBootstrap_InitialComponentContext();
378 css::uno::Reference< container::XHierarchicalNameAccess > xTDmgr(
379 xContext->getValueByName(
380 "/singletons/com.sun.star.reflection."
381 "theTypeDescriptionManager" ),
382 UNO_QUERY_THROW );
383
384 // The registries are consumed twice, once to insert them into the
385 // TypeDescriptionManager so that TypeEmitter can work on
386 // css.star.reflection.XTypeDescription representation, and once
387 // directly as unoidl::Provider instances to keep track which types are
388 // coming from the mandatory registries for the "no explicit types
389 // given" case (which iterates over the full TypeDescriptionManager
390 // now); a welcome clean-up would be to make TypeEmitter work on
391 // unoidl::Entity directly like the other codemakers:
392 css::uno::Reference< container::XSet > xSet( xTDmgr, UNO_QUERY_THROW );
393 rtl::Reference unoidlMgr(new unoidl::Manager);
394 std::vector< rtl::Reference< unoidl::Provider > > unoidlMandatoryProvs;
395 for (auto& rRegistry : extra_registries)
396 {
397 xSet->insert(Any(rRegistry));
398 unoidlMgr->addProvider(rRegistry);
399 }
400 for (auto& rRegistry : mandatory_registries)
401 {
402 xSet->insert(Any(rRegistry));
403 rtl::Reference< unoidl::Provider > prov(unoidlMgr->addProvider(rRegistry));
404 unoidlMandatoryProvs.push_back(prov);
405 }
406
407 if (0 == output.getLength()) // no output file specified
408 {
409 // if only one rdb has been given, then take rdb name
410 if (1 == mandatory_registries.size())
411 {
412 output = mandatory_registries[ 0 ];
413 output = output.copy( output.lastIndexOf( '/' ) +1 );
414 sal_Int32 dot = output.lastIndexOf( '.' );
415 if (dot > 0)
416 output = output.copy( 0, dot );
417 }
418 else
419 {
420 output = "cli_unotypes";
421 }
422 }
423 output = path_make_absolute_file_url( output );
424 sal_Int32 slash = output.lastIndexOf( '/' );
425 OUString sys_output_dir;
426 if (FileBase::E_None != FileBase::getSystemPathFromFileURL(
427 output.copy( 0, slash ), sys_output_dir ))
428 {
429 throw RuntimeException(
430 "cannot get system path from file url " +
431 output.copy( 0, slash ) );
432 }
433 OUString filename( output.copy( slash +1 ) );
434 sal_Int32 dot = filename.lastIndexOf( '.' );
435 OUString name( filename );
436 if (dot < 0) // has no extension
437 filename += ".dll";
438 else
439 name = name.copy( 0, dot );
440 ::System::String ^ output_dir = ustring_to_String( sys_output_dir );
441 ::System::String ^ output_file = ustring_to_String( filename );
442
443 //Get the key pair for making a strong name
444 StrongNameKeyPair^ kp = nullptr;
445 if (keyfile.getLength() > 0)
446 {
447 ::System::String ^ sKeyFile = ustring_to_String(keyfile);
448 try {
449 System::IO::FileStream^ fs = gcnew System::IO::FileStream(
450 sKeyFile, System::IO::FileMode::Open,
451 System::IO::FileAccess::Read, System::IO::FileShare::Read);
452 kp = gcnew StrongNameKeyPair(fs);
453 fs->Close();
454 }
455 catch (System::IO::FileNotFoundException ^ )
456 {
457 throw Exception("Could not find the keyfile. Verify the --keyfile argument!", 0);
458 }
459 }
460 else
461 {
462 if (g_bVerbose)
463 {
464 ::System::Console::Write(
465 "> no key file specified. Cannot create strong name!\n");
466 }
467 }
468 // setup assembly info: xxx todo set more? e.g. avoid strong versioning
469 AssemblyName ^ assembly_name = gcnew AssemblyName();
470 assembly_name->CodeBase = output_dir;
471 assembly_name->Name = gcnew ::System::String(
472 reinterpret_cast<wchar_t const *>(name.getStr()));
473 if (kp != nullptr)
474 assembly_name->KeyPair= kp;
475
476 if (version.getLength() != 0)
477 {
478 assembly_name->Version=
479 gcnew ::System::Version( ustring_to_String( version ) );
480 }
481
482 // app domain
483 ::System::AppDomain ^ current_appdomain =
484 ::System::AppDomain::CurrentDomain;
485
486// Weird warning from this statement
487// warning C4538: 'cli::array<Type> ^' : const/volatile qualifiers on this type are not supported
488// Could be a compiler bug, says http://stackoverflow.com/questions/12151060/seemingly-inappropriate-compilation-warning-with-c-cli
489#pragma warning (push)
490#pragma warning (disable: 4538)
491 // target assembly
492 Emit::AssemblyBuilder ^ assembly_builder =
493 current_appdomain->DefineDynamicAssembly(
494 assembly_name, Emit::AssemblyBuilderAccess::Save, output_dir );
495#pragma warning (pop)
496
497 if (product.getLength() != 0)
498 {
499 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^> (1);
500 cli::array< ::System::Object^>^args = gcnew cli::array< ::System::Object^>(1);
501 params[ 0 ] = ::System::String::typeid;
502 args[ 0 ] = ustring_to_String( product );
503 assembly_builder->SetCustomAttribute(
504 gcnew Emit::CustomAttributeBuilder(
505 (AssemblyProductAttribute::typeid)->GetConstructor(
506 params ), args ) );
507 }
508 if (description.getLength() != 0)
509 {
510 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
511 cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
512 params[ 0 ] = ::System::String::typeid;
513 args[ 0 ] = ustring_to_String( description );
514 assembly_builder->SetCustomAttribute(
515 gcnew Emit::CustomAttributeBuilder(
516 (AssemblyDescriptionAttribute::typeid)->GetConstructor(
517 params ), args ) );
518 }
519 if (company.getLength() != 0)
520 {
521 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
522 cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
523 params[ 0 ] = ::System::String::typeid;
524 args[ 0 ] = ustring_to_String( company );
525 assembly_builder->SetCustomAttribute(
526 gcnew Emit::CustomAttributeBuilder(
527 (AssemblyCompanyAttribute::typeid)->GetConstructor(
528 params ), args ) );
529 }
530 if (copyright.getLength() != 0)
531 {
532 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
533 cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
534 params[ 0 ] = ::System::String::typeid;
535 args[ 0 ] = ustring_to_String( copyright );
536 assembly_builder->SetCustomAttribute(
537 gcnew Emit::CustomAttributeBuilder(
538 (AssemblyCopyrightAttribute::typeid)->GetConstructor(
539 params ), args ) );
540 }
541 if (trademark.getLength() != 0)
542 {
543 cli::array< ::System::Type^>^ params = gcnew cli::array< ::System::Type^>(1);
544 cli::array< ::System::Object^>^ args = gcnew cli::array< ::System::Object^>(1);
545 params[ 0 ] = ::System::String::typeid;
546 args[ 0 ] = ustring_to_String( trademark );
547 assembly_builder->SetCustomAttribute(
548 gcnew Emit::CustomAttributeBuilder(
549 (AssemblyTrademarkAttribute::typeid)->GetConstructor(
550 params ), args ) );
551 }
552
553 // load extra assemblies
554 cli::array<Assembly^>^ assemblies =
555 gcnew cli::array<Assembly^>(extra_assemblies.size());
556 for ( size_t pos = 0; pos < extra_assemblies.size(); ++pos )
557 {
558 assemblies[ pos ] = Assembly::LoadFrom(
559 ustring_to_String( extra_assemblies[ pos ] ) );
560 }
561
562 // type emitter
563 TypeEmitter ^ type_emitter = gcnew TypeEmitter(
564 assembly_builder->DefineDynamicModule( output_file ), assemblies );
565 // add handler resolving assembly's types
566 ::System::ResolveEventHandler ^ type_resolver =
567 gcnew ::System::ResolveEventHandler(
568 type_emitter, &TypeEmitter::type_resolve );
569 current_appdomain->TypeResolve += type_resolver;
570
571 // and emit types to it
572 if (explicit_types.empty())
573 {
574 css::uno::Reference< reflection::XTypeDescriptionEnumeration > xTD_enum(
575 css::uno::Reference< reflection::XTypeDescriptionEnumerationAccess >(
576 xTDmgr, UNO_QUERY_THROW )
577 ->createTypeDescriptionEnumeration(
578 OUString() /* all IDL modules */,
579 Sequence< TypeClass >() /* all classes of types */,
580 reflection::TypeDescriptionSearchDepth_INFINITE ) );
581 while (xTD_enum->hasMoreElements())
582 {
583 css::uno::Reference< reflection::XTypeDescription > td(
584 xTD_enum->nextTypeDescription());
585 OUString name(td->getName());
586 bool bEmit = std::any_of(unoidlMandatoryProvs.begin(), unoidlMandatoryProvs.end(),
587 [&name](rtl::Reference<unoidl::Provider>& rProv) { return rProv->findEntity(name).is(); });
588 if (bEmit) {
589 type_emitter->get_type(td);
590 }
591 }
592 }
593 else
594 {
595 for ( size_t nPos = explicit_types.size(); nPos--; )
596 {
597 type_emitter->get_type(
598 css::uno::Reference< reflection::XTypeDescription >(
599 xTDmgr->getByHierarchicalName( explicit_types[ nPos ] ),
600 UNO_QUERY_THROW ) );
601 }
602 }
603 type_emitter->finish();
604
605 if (g_bVerbose)
606 {
607 ::System::Console::Write(
608 "> saving assembly {0}{1}{2}...",
609 output_dir,
610 gcnew ::System::String(
611 ::System::IO::Path::DirectorySeparatorChar, 1 ),
612 output_file );
613 }
614 assembly_builder->Save( output_file );
615 if (g_bVerbose)
616 {
617 ::System::Console::WriteLine( "ok." );
618 }
619 current_appdomain->TypeResolve -= type_resolver;
620 }
622 {
623 std::cerr << "ERROR: No such file <" << e.getUri() << ">\n";
624 return EXIT_FAILURE;
625 }
627 {
628 std::cerr
629 << "ERROR: Bad format of <" << e.getUri() << ">, \""
630 << e.getDetail() << "\"\n";
631 return EXIT_FAILURE;
632 }
633 catch (Exception & exc)
634 {
635 OString msg(
636 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
637 fprintf(
638 stderr, "\n> error: %s\n> dying abnormally...\n", msg.getStr() );
639 ret = 1;
640 }
641 catch (::System::Exception ^ exc)
642 {
643 OString msg( OUStringToOString(
644 String_to_ustring( exc->ToString() ),
645 osl_getThreadTextEncoding() ) );
646 fprintf(
647 stderr,
648 "\n> error: .NET exception occurred: %s\n> dying abnormally...",
649 msg.getStr() );
650 ret = 1;
651 }
652
653 try
654 {
655 css::uno::Reference< lang::XComponent > xComp( xContext, UNO_QUERY );
656 if (xComp.is())
657 xComp->dispose();
658 }
659 catch (Exception & exc)
660 {
661 OString msg(
662 OUStringToOString( exc.Message, osl_getThreadTextEncoding() ) );
663 fprintf(
664 stderr,
665 "\n> error disposing component context: %s\n"
666 "> dying abnormally...\n",
667 msg.getStr() );
668 ret = 1;
669 }
670
671 return ret;
672}
673
674/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const OUString & getUri() const
SAL_IMPLEMENT_MAIN()
int nCount
const char * name
sal_uInt16 nPos
std::unique_ptr< sal_Int32[]> pData
inline ::System::String ustring_to_String(OUString const &ustr)
static char const s_usingText[]
bool g_bVerbose
static const OptionInfo s_option_infos[]
static bool is_option(OptionInfo const *option_info, sal_uInt32 *pIndex)
static OUString const & path_get_working_dir()
OUString String_to_ustring(::System::String ^ str)
static OUString path_make_absolute_file_url(OUString const &path)
static bool read_argument(OUString *pValue, OptionInfo const *option_info, sal_uInt32 *pIndex)
static OptionInfo const * get_option_info(OUString const &opt, sal_Unicode copt='\0')
static bool read_option(bool *flag, OptionInfo const *option_info, sal_uInt32 *pIndex)
@ Exception
index
args
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
SwNodeOffset abs(const SwNodeOffset &a)
sal_Unicode m_short_option
sal_uInt32 m_name_length
sal_uInt16 sal_Unicode
size_t pos