1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "codemaker/commoncpp.hxx"
25 
26 #include "skeletoncommon.hxx"
27 #include "skeletoncpp.hxx"
28 
29 using namespace ::rtl;
30 using namespace ::codemaker::cpp;
31 
32 namespace skeletonmaker { namespace cpp {
33 
printType(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,codemaker::UnoType::Sort sort,RTTypeClass typeClass,OString const & name,sal_Int32 rank,std::vector<OString> const & arguments,short referenceType,bool defaultvalue)34 void printType(std::ostream & o,
35     ProgramOptions const & options, TypeManager const & manager,
36     codemaker::UnoType::Sort sort, RTTypeClass typeClass,
37     OString const & name, sal_Int32 rank,
38     std::vector< OString > const & arguments, short referenceType,
39     bool defaultvalue)
40 {
41     if (defaultvalue && rank == 0 && sort <= codemaker::UnoType::SORT_CHAR) {
42         switch (sort)
43         {
44         case codemaker::UnoType::SORT_BOOLEAN:
45             o << "sal_False";
46             return;
47         case codemaker::UnoType::SORT_CHAR:
48         case codemaker::UnoType::SORT_BYTE:
49         case codemaker::UnoType::SORT_SHORT:
50         case codemaker::UnoType::SORT_UNSIGNED_SHORT:
51         case codemaker::UnoType::SORT_LONG:
52         case codemaker::UnoType::SORT_UNSIGNED_LONG:
53         case codemaker::UnoType::SORT_HYPER:
54         case codemaker::UnoType::SORT_UNSIGNED_HYPER:
55         case codemaker::UnoType::SORT_FLOAT:
56         case codemaker::UnoType::SORT_DOUBLE:
57             o << "0";
58             return;
59         case codemaker::UnoType::SORT_VOID:
60         case codemaker::UnoType::SORT_STRING:
61         case codemaker::UnoType::SORT_TYPE:
62         case codemaker::UnoType::SORT_ANY:
63         case codemaker::UnoType::SORT_COMPLEX:
64             break;
65         }
66     }
67 
68     if (defaultvalue && referenceType == 16) {
69         if (typeClass == RT_TYPE_ENUM) {
70             typereg::Reader reader(manager.getTypeReader(name));
71             o << name.copy(name.lastIndexOf('/'))
72               << "_"
73               << codemaker::convertString(reader.getFieldName(0));
74         }
75         return;
76     }
77     bool bReference = false;
78     if (((sort > codemaker::UnoType::SORT_CHAR ||
79           rank > 0) && referenceType != 8 &&
80          !(typeClass == RT_TYPE_ENUM && referenceType == 4 && rank == 0)) ||
81         (sort <= codemaker::UnoType::SORT_CHAR && referenceType == 2))
82     {
83         bReference = true;
84     }
85 
86     if (bReference && referenceType == 4)
87         o << "const ";
88 
89     for (sal_Int32 i = 0; i < rank; ++i) {
90         o << ((options.shortnames) ? "css::uno::Sequence< " :
91               "::com::sun::star::uno::Sequence< ");
92     }
93     if (typeClass == RT_TYPE_INTERFACE && referenceType > 0) {
94         o << ((options.shortnames) ? "css::uno::Reference< " :
95               "::com::sun::star::uno::Reference< ");
96     }
97 
98     o << scopedCppName(codemaker::cpp::translateUnoToCppType(
99                            sort, typeClass, name, false),
100                        false, options.shortnames && referenceType > 0);
101 
102     if (typeClass == RT_TYPE_INTERFACE && referenceType > 0)
103         o << " >";
104 
105     if (!arguments.empty()) {
106         o << "< ";
107         for (std::vector< OString >::const_iterator i(arguments.begin());
108              i != arguments.end(); ++i)
109         {
110             if (i != arguments.begin())
111                 o << ", ";
112 
113             printType(o, options, manager, *i, 1, false);
114         }
115         o << " >";
116     }
117 
118     for (sal_Int32 i = 0; i < rank; ++i)
119         o << " >";
120 
121     if (bReference && referenceType > 1)
122         o << " &";
123 
124     if (referenceType == 8 && (sort > codemaker::UnoType::SORT_CHAR || rank > 0))
125         o << "()";
126 }
127 
printType(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,OString const & type,short referenceType,bool defaultvalue)128 void printType(std::ostream & o,
129     ProgramOptions const & options, TypeManager const & manager,
130     OString const & type, short referenceType, bool defaultvalue)
131 {
132     RTTypeClass typeClass;
133     OString name;
134     sal_Int32 rank;
135     std::vector< OString > arguments;
136     codemaker::UnoType::Sort sort = codemaker::decomposeAndResolve(
137         manager, type, true, true, true, &typeClass, &name, &rank, &arguments);
138     printType(o,
139         options, manager, sort, typeClass, name, rank, arguments,
140         referenceType, defaultvalue);
141 }
142 
printConstructorParameters(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,typereg::Reader const & outerReader,std::vector<OString> const & arguments)143 bool printConstructorParameters(std::ostream & o,
144     ProgramOptions const & options, TypeManager const & manager,
145     typereg::Reader const & reader, typereg::Reader const & outerReader,
146     std::vector< OString > const & arguments)
147 {
148     bool previous = false;
149     if (reader.getSuperTypeCount() != 0) {
150         OString super(
151             codemaker::convertString(reader.getSuperTypeName(0)));
152         typereg::Reader superReader(manager.getTypeReader(super));
153         if (!superReader.isValid())
154             throw CannotDumpException("Bad type library entity " + super);
155 
156         previous = printConstructorParameters(o,
157             options, manager, superReader, outerReader, arguments);
158     }
159     for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) {
160         if (previous)
161             o << ", ";
162         else
163             previous = true;
164 
165         if ((reader.getFieldFlags(i) & RT_ACCESS_PARAMETERIZED_TYPE) == 0) {
166             printType(o, options, manager,
167                       codemaker::convertString(reader.getFieldTypeName(i)), 4);
168         } else if (arguments.empty()) {
169             // ToDo !
170             // o << "com::sun::star::uno::Any";
171         } else {
172             sal_uInt16 tparam = 0;
173             while (outerReader.getReferenceTypeName(tparam)
174                    != reader.getFieldTypeName(i))
175             {
176                 ++tparam;
177                 OSL_ASSERT(tparam < outerReader.getReferenceCount());
178             }
179             // assume std::vector< OString >::size_type is at least as
180             // large as sal_uInt16:
181             printType(o, options, manager, arguments[tparam], 4);
182         }
183         o << ' '
184           << (codemaker::cpp::translateUnoToCppIdentifier(
185                   codemaker::convertString(reader.getFieldName(i)),
186                   "param").
187               getStr());
188     }
189     return previous;
190 }
191 
printConstructor(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,std::vector<OString> const & arguments)192 void printConstructor(std::ostream & o,
193     ProgramOptions const & options, TypeManager const & manager,
194     typereg::Reader const & reader,
195     std::vector< OString > const & arguments)
196 {
197     OString type(codemaker::convertString(reader.getTypeName()));
198     o << "public ";
199     o << type.copy(type.lastIndexOf('/') + 1) << '(';
200     printConstructorParameters(o, options, manager, reader, reader,
201                                arguments);
202     o << ");\n";
203 }
204 
printMethodParameters(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,sal_uInt16 method,bool previous,bool withtype)205 void printMethodParameters(std::ostream & o,
206     ProgramOptions const & options, TypeManager const & manager,
207     typereg::Reader const & reader, sal_uInt16 method, bool previous,
208     bool withtype)
209 {
210     short referenceType = 4;
211     for (sal_uInt16 i = 0; i < reader.getMethodParameterCount(method); ++i) {
212         if (previous)
213             o << ", ";
214 
215         previous = true;
216 
217         if (reader.getMethodParameterFlags(method, i) == RT_PARAM_OUT
218             || reader.getMethodParameterFlags(method, i) == RT_PARAM_INOUT)
219         {
220             referenceType = 2;
221         } else {
222             referenceType = 4;
223         }
224 
225         if (withtype) {
226             printType(o, options, manager,
227                 codemaker::convertString(
228                     reader.getMethodParameterTypeName(method, i)),
229                          referenceType);
230             o << ' ';
231         }
232 
233         o << (codemaker::cpp::translateUnoToCppIdentifier(
234                   codemaker::convertString(
235                       reader.getMethodParameterName(method, i)),
236                   "param").
237               getStr());
238     }
239 }
240 
printExceptionSpecification(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,sal_uInt16 method)241 void printExceptionSpecification(std::ostream & o,
242     ProgramOptions const & options, TypeManager const & manager,
243     typereg::Reader const & reader, sal_uInt16 method)
244 {
245     o << ((options.shortnames) ? " throw (css::uno::RuntimeException" :
246           " throw (::com::sun::star::uno::RuntimeException");
247     if (reader.getMethodExceptionCount(method) > 0) {
248         for (sal_uInt16 i = 0; i < reader.getMethodExceptionCount(method); ++i) {
249             o << ", ";
250             printType(o, options, manager,
251                 codemaker::convertString(
252                     reader.getMethodExceptionTypeName(method, i)), 1);
253         }
254     }
255     o << ")";
256 }
257 
printSetPropertyMixinBody(std::ostream & o,typereg::Reader const & reader,sal_uInt16 field,sal_uInt16 method)258 void printSetPropertyMixinBody(std::ostream & o,
259                                typereg::Reader const & reader,
260                                sal_uInt16 field,
261                                sal_uInt16 method)
262 {
263     RTFieldAccess propFlags = checkAdditionalPropertyFlags(reader, field, method);
264     OString fieldname = codemaker::convertString(reader.getFieldName(field));
265     bool bound = (reader.getFieldFlags(field) & RT_ACCESS_BOUND ? true : false);
266 
267     o << "\n{\n";
268 
269     if (bound)
270         o << "    BoundListeners l;\n";
271 
272     if (propFlags & RT_ACCESS_CONSTRAINED) {
273         OString fieldtype = codemaker::convertString(
274                                 reader.getFieldTypeName(field));
275 
276         sal_Int32 index = fieldtype.lastIndexOf('<');
277         sal_Int32 nPos=0;
278 		bool single = true;
279 		bool optional = false;
280 		OStringBuffer buffer1(64);
281 		OStringBuffer buffer2(64);
282         do
283         {
284             OString s(fieldtype.getToken(0, '<', nPos));
285 			OString t = s.copy(s.lastIndexOf('/')+1);
286 
287             if (t.equals("Optional")) {
288                 optional=true;
289                 if (single) {
290                     single=false;
291                     buffer1.append("the_value.IsPresent");
292                     buffer2.append("the_value.Value");
293                 } else {
294                     buffer1.insert(0, t);
295                     buffer1.append(".IsPresent");
296                     buffer2.insert(0, t);
297                     buffer2.append(".Value");
298                 }
299             } else {
300                 if (single) {
301                     single=false;
302                     if (!optional)
303                         buffer1.append("the_value.Value");
304 
305                     buffer2.append("the_value.Value");
306                 } else {
307                     if (!optional) {
308                         buffer1.insert(0, t);
309                         buffer1.append(".Value");
310                     }
311                     buffer2.insert(0, t);
312                     buffer2.append(".Value");
313                 }
314             }
315         } while( nPos <= index );
316 
317         o << "    css::uno::Any v;\n";
318         if (optional) {
319             o << "    if(" << buffer1.makeStringAndClear() << ")\n    {\n"
320               << "        v <<= " << buffer2.makeStringAndClear() << ";\n    }\n";
321         } else {
322             o << "    v <<= " << buffer2.makeStringAndClear() << ";\n\n";
323         }
324 
325         o << "    prepareSet(\n        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(\""
326           << fieldname << "\")),\n        css::uno::Any(), v, ";
327     } else {
328         o << "    prepareSet(\n        rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(\""
329           << fieldname << "\")),\n        css::uno::Any(), css::uno::Any(), ";
330     }
331 
332     if (bound)
333         o << "&l);\n";
334     else
335         o << "0);\n";
336 
337     o << "    {\n        osl::MutexGuard g(m_aMutex);\n        m_"
338       << fieldname << " = the_value;\n    }\n";
339 
340     if (bound)
341         o << "    l.notify();\n";
342 
343     o  << "}\n\n";
344 }
345 
346 void generateXPropertySetBodies(std::ostream& o,
347                                 const OString & classname,
348                                 const OString & interfaceName);
349 void generateXFastPropertySetBodies(std::ostream& o,
350                                     const OString & classname,
351                                     const OString & interfaceName);
352 void generateXPropertyAccessBodies(std::ostream& o,
353                                    const OString & classname,
354                                    const OString & interfaceName);
355 
356 void generateXAddInBodies(std::ostream& o, const OString & classname);
357 
358 void generateXLocalizable(std::ostream& o, const OString & classname);
359 
360 void generateXCompatibilityNamesBodies(std::ostream& o, const OString & classname);
361 
362 void generateXInitialization(std::ostream& o, const OString & classname);
363 
364 void generateXDispatch(std::ostream& o,
365                        const OString & classname,
366                        const ProtocolCmdMap & protocolCmdMap);
367 
368 void generateXDispatchProvider(std::ostream& o,
369                                const OString & classname,
370                                const ProtocolCmdMap & protocolCmdMap);
371 
372 
printMethods(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,codemaker::GeneratedTypeSet & generated,OString const & delegate,OString const & classname,OString const & indentation,bool defaultvalue,OString const & propertyhelper)373 void printMethods(std::ostream & o,
374     ProgramOptions const & options, TypeManager const & manager,
375     typereg::Reader const & reader, codemaker::GeneratedTypeSet & generated,
376     OString const & delegate, OString const & classname,
377     OString const & indentation, bool defaultvalue,
378     OString const & propertyhelper)
379 {
380     OString type(codemaker::convertString(reader.getTypeName()));
381     if (generated.contains(type) || type.equals("com/sun/star/uno/XInterface") ||
382         (defaultvalue &&
383          ( type.equals("com/sun/star/lang/XComponent") ||
384            type.equals("com/sun/star/lang/XTypeProvider") ||
385            type.equals("com/sun/star/uno/XWeak")) ) )
386     {
387         return;
388     }
389 
390     static OString sd(RTL_CONSTASCII_STRINGPARAM("_"));
391     bool body = ((delegate.getLength() > 0) ? true : false);
392     bool defaultbody = ((delegate.equals(sd)) ? true : false);
393 
394     if (body && propertyhelper.getLength() > 1) {
395         if ( type.equals("com/sun/star/beans/XPropertySet")) {
396             generated.add(type);
397             generateXPropertySetBodies(
398                 o, classname, scopedCppName(propertyhelper, false, true));
399             return;
400         } else if ( type.equals("com/sun/star/beans/XFastPropertySet")) {
401             generated.add(type);
402             generateXFastPropertySetBodies(
403                 o, classname, scopedCppName(propertyhelper, false, true));
404             return;
405         } else if ( type.equals("com/sun/star/beans/XPropertyAccess")) {
406             generated.add(type);
407             generateXPropertyAccessBodies(
408                 o, classname, scopedCppName(propertyhelper, false, true));
409             return;
410         }
411     }
412 
413     if (body && options.componenttype == 2) {
414         if (type.equals("com/sun/star/lang/XServiceName")) {
415             o << "// ::com::sun::star::lang::XServiceName:\n"
416                 "::rtl::OUString SAL_CALL " << classname << "getServiceName() "
417                 "throw (css::uno::RuntimeException)\n{\n    "
418                 "return ::rtl::OUString::createFromAscii("
419                 "sADDIN_SERVICENAME);\n}\n";
420             generated.add(type);
421             return;
422         } else if (type.equals("com/sun/star/sheet/XAddIn")) {
423             generateXAddInBodies(o, classname);
424             generated.add(type);
425 
426             // special handling of XLocalizable -> parent of XAddIn
427             if (!generated.contains("com/sun/star/lang/XLocalizable")) {
428                 generateXLocalizable(o, classname);
429                 generated.add("com/sun/star/lang/XLocalizable");
430             }
431             return;
432         } else if (type.equals("com/sun/star/lang/XLocalizable")) {
433             generateXLocalizable(o, classname);
434             generated.add(type);
435             return;
436         } else if (type.equals("com/sun/star/sheet/XCompatibilityNames")) {
437             generateXCompatibilityNamesBodies(o, classname);
438             generated.add(type);
439             return;
440         }
441     }
442 
443     if (body && options.componenttype == 3) {
444         if (type.equals("com/sun/star/lang/XInitialization")) {
445             generateXInitialization(o, classname);
446             generated.add(type);
447             return;
448         } else if (type.equals("com/sun/star/frame/XDispatch")) {
449             generateXDispatch(o, classname, options.protocolCmdMap);
450             generated.add(type);
451             return;
452         } else if (type.equals("com/sun/star/frame/XDispatchProvider")) {
453             generateXDispatchProvider(o, classname, options.protocolCmdMap);
454             generated.add(type);
455             return;
456         }
457     }
458 
459     generated.add(type);
460     if (options.all || defaultvalue) {
461         for (sal_uInt16 i = 0; i < reader.getSuperTypeCount(); ++i) {
462             typereg::Reader super(
463                 manager.getTypeReader(
464                     codemaker::convertString(
465                         reader.getSuperTypeName(i))));
466             if (!super.isValid()) {
467                 throw CannotDumpException(
468                     "Bad type library entity "
469                     + codemaker::convertString(
470                         reader.getSuperTypeName(i)));
471             }
472 
473 			OString stype(codemaker::convertString(super.getTypeName()));
474             printMethods(o, options, manager, super, generated, delegate,
475                             classname, indentation, defaultvalue, propertyhelper);
476         }
477 
478         if (reader.getFieldCount() > 0 || reader.getMethodCount() > 0) {
479             o << indentation << "// ";
480             printType(o, options, manager, type, 0);
481             o << ":\n";
482         }
483     }
484     sal_uInt16 method = 0;
485     for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) {
486         o << indentation;
487         if (!body)
488             o << "virtual ";
489 
490         printType(o, options, manager,
491                   codemaker::convertString(reader.getFieldTypeName(i)), 1);
492         o << " SAL_CALL ";
493         if (classname.getLength() > 0)
494             o << classname;
495 
496         o << "get"
497           << codemaker::convertString(reader.getFieldName(i)).getStr()
498           << "()";
499         if (method < reader.getMethodCount()
500             && reader.getMethodFlags(method) == RT_MODE_ATTRIBUTE_GET
501             && reader.getMethodName(method) == reader.getFieldName(i))
502         {
503             printExceptionSpecification(o, options, manager, reader, method++);
504         } else {
505             o << ((options.shortnames) ? " throw (css::uno::RuntimeException)" :
506                   " throw (::com::sun::star::uno::RuntimeException)");
507         }
508         if (body) {
509             if (defaultbody) {
510                 if (propertyhelper.getLength() > 0) {
511                     o << "\n{\n    osl::MutexGuard g(m_aMutex);\n    return m_"
512                       << codemaker::convertString(reader.getFieldName(i)).getStr()
513                       << ";\n}\n\n";
514                 } else {
515                     o << "\n{\n    return ";
516                     if (options.componenttype == 1) {
517                         o << "m_"
518                           << codemaker::convertString(
519                               reader.getFieldName(i)).getStr();
520                     } else {
521                         printType(o, options, manager,
522                                   codemaker::convertString(
523                                       reader.getFieldTypeName(i)),
524                                   8, true);
525                     }
526                     o << ";\n}\n\n";
527                 }
528             } else {
529                 o << "\n" << indentation << "{\n" << indentation << "    return "
530                   << delegate.getStr() << "get"
531                   << codemaker::convertString(reader.getFieldName(i)).getStr()
532                   << "();\n" << indentation << "}\n\n";
533             }
534         } else {
535             o << ";\n";
536         }
537 
538         if ((reader.getFieldFlags(i) & RT_ACCESS_READONLY) == 0) {
539             o << indentation;
540             if (!body)
541                 o << "virtual ";
542 
543             o << "void SAL_CALL ";
544             if (classname.getLength() > 0)
545                 o << classname;
546 
547             o << "set"
548               << (codemaker::convertString(reader.getFieldName(i)).getStr())
549               << '(';
550             printType(o, options, manager,
551                       codemaker::convertString(reader.getFieldTypeName(i)), 4);
552             o << " the_value)";
553             if (method < reader.getMethodCount()
554                 && reader.getMethodFlags(method) == RT_MODE_ATTRIBUTE_SET
555                 && reader.getMethodName(method) == reader.getFieldName(i))
556             {
557                 printExceptionSpecification(o, options, manager, reader, method++);
558             } else {
559                 o << ((options.shortnames) ? " throw (css::uno::RuntimeException)" :
560                       " throw (::com::sun::star::uno::RuntimeException)");
561             }
562             if (body) {
563                 if (defaultbody) {
564                     if (propertyhelper.getLength() > 0) {
565                         printSetPropertyMixinBody(o, reader, i, method);
566                     } else {
567                         if (options.componenttype == 1) {
568                             o << "\n{\n    m_"
569                               << codemaker::convertString(
570                                   reader.getFieldName(i)).getStr()
571                               << " = the_value;\n}\n\n";
572                         } else {
573                             o << "\n{\n\n}\n\n";
574                         }
575                     }
576                 } else {
577                     o << "\n" << indentation << "{\n" << indentation << "    "
578                       << delegate.getStr() << "set"
579                       << codemaker::convertString(reader.getFieldName(i)).getStr()
580                       << "(the_value);\n" << indentation << "}\n\n";
581                 }
582             } else {
583                 o << ";\n";
584             }
585         }
586     }
587     for (; method < reader.getMethodCount(); ++method) {
588         o << indentation;
589         if (!body)
590             o << "virtual ";
591 
592         printType(o, options, manager,
593                   codemaker::convertString(
594                       reader.getMethodReturnTypeName(method)), 1);
595         o << " SAL_CALL ";
596         if (classname.getLength() > 0)
597             o << classname;
598 
599         const OString methodName(codemaker::convertString(reader.getMethodName(method)));
600 
601         o << methodName << '(';
602         printMethodParameters(o, options, manager, reader, method, false, true);
603         o << ')';
604         printExceptionSpecification(o, options, manager, reader, method);
605         if (body) {
606             static OUString s(RTL_CONSTASCII_USTRINGPARAM("void"));
607             if (defaultbody) {
608                 o << "\n{\n";
609                 if (!reader.getMethodReturnTypeName(method).equals(s)) {
610                     o << "    // TODO: Exchange the default return implementation for \""
611                       << methodName << "\" !!!\n";
612                     o << "    // Exchange the default return implementation.\n"
613                         "    // NOTE: Default initialized polymorphic structs "
614                         "can cause problems because of\n    // missing default "
615                         "initialization of primitive types of some C++ compilers or"
616                         "\n    // different Any initialization in Java and C++ "
617                         "polymorphic structs.\n    return ";
618                     printType(o, options, manager,
619                         codemaker::convertString(
620                             reader.getMethodReturnTypeName(method)), 8, true);
621                     o << ";";
622                 } else {
623                     o << "    // TODO: Insert your implementation for \""
624                       << methodName << "\" here.";
625                 }
626                 o << "\n}\n\n";
627             } else {
628                 o << "\n" << indentation << "{\n" << indentation << "    ";
629                 if (!reader.getMethodReturnTypeName(method).equals(s))
630                     o << "return ";
631 
632                 o << delegate.getStr()
633                   << (codemaker::convertString(
634                           reader.getMethodName(method)).getStr())
635                   << '(';
636                 printMethodParameters(o, options, manager, reader, method,
637                                       false, false);
638                 o << ");\n" << indentation << "}\n\n";
639             }
640         } else {
641             o << ";\n";
642         }
643     }
644 
645     if (method > 0 && !body)
646         o << "\n";
647 }
648 
printConstructionMethods(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader)649 void printConstructionMethods(std::ostream & o,
650     ProgramOptions const & options, TypeManager const & manager,
651     typereg::Reader const & reader)
652 {
653     for (sal_uInt16 i = 0; i < reader.getMethodCount(); ++i) {
654         o << "static ";
655         printType(o,
656             options, manager,
657             codemaker::convertString(reader.getSuperTypeName(0)), 1);
658         o << ' ';
659         if (reader.getMethodName(i).getLength() == 0) {
660             o << "create";
661         } else {
662             o << (codemaker::cpp::translateUnoToCppIdentifier(
663                       codemaker::convertString(reader.getMethodName(i)),
664                       "method").
665                   getStr());
666         }
667         o << ((options.shortnames) ? "(css::uno::Reference< css" :
668               "(::com::sun::star::uno::Reference< ::com::sun::star")
669           << "::uno::XComponentContext > const & the_context";
670         printMethodParameters(o, options, manager, reader, i,
671                               true, true);
672         o << ')';
673         printExceptionSpecification(o, options, manager, reader, i);
674         o << ";\n";
675     }
676 }
677 
printServiceMembers(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,typereg::Reader const & reader,OString const & type,OString const & delegate)678 void printServiceMembers(std::ostream & o,
679     ProgramOptions const & options, TypeManager const & manager,
680     typereg::Reader const & reader, OString const & type,
681     OString const & delegate)
682 {
683     for (sal_uInt16 i = 0; i < reader.getReferenceCount(); ++i) {
684         OString referenceType(
685             codemaker::convertString(
686                 reader.getReferenceTypeName(i)).replace('/', '.'));
687 
688         if ( reader.getReferenceSort(i) == RT_REF_SUPPORTS ) {
689             o << "\n// supported interface " << referenceType.getStr() << "\n";
690             generateDocumentation(o, options, manager, referenceType, delegate);
691         } else if ( reader.getReferenceSort(i) == RT_REF_EXPORTS ) {
692             o << "\n// exported service " << referenceType.getStr() << "\n";
693             generateDocumentation(o, options, manager, referenceType, delegate);
694             o << "\n// end of exported service " << referenceType.getStr() << "\n";
695         }
696     }
697 
698     if (delegate.getLength() == 0) {
699         o << "\n// properties of service \""<< type.getStr() << "\"\n";
700         for (sal_uInt16 i = 0; i < reader.getFieldCount(); ++i) {
701             OString fieldName(
702                 codemaker::convertString(reader.getFieldName(i)));
703             OString fieldType(
704                 codemaker::convertString(reader.getFieldTypeName(i)));
705 
706             o << "// private ";
707             printType(o, options, manager, fieldType, 1);
708             o << " "
709               << codemaker::cpp::translateUnoToCppIdentifier(
710                   fieldName, "property").getStr()
711               << ";\n";
712         }
713     }
714 }
715 
printMapsToCppType(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,codemaker::UnoType::Sort sort,RTTypeClass typeClass,OString const & name,sal_Int32 rank,std::vector<OString> const & arguments,const char * cppTypeSort)716 void printMapsToCppType(std::ostream & o,
717     ProgramOptions const & options, TypeManager const & manager,
718     codemaker::UnoType::Sort sort, RTTypeClass typeClass,
719     OString const & name, sal_Int32 rank,
720     std::vector< OString > const & arguments, const char * cppTypeSort)
721 {
722     o << "maps to C++ ";
723     if (cppTypeSort != 0)
724         o << cppTypeSort << ' ';
725 
726     o << "type \"";
727     if (rank == 0 && name == "com/sun/star/uno/XInterface") {
728         o << "Reference< com::sun::star::uno::XInterface >";
729     } else {
730         printType(o, options, manager, sort, typeClass, name, rank, arguments, 0);
731     }
732     o << '"';
733 }
734 
generateDocumentation(std::ostream & o,ProgramOptions const & options,TypeManager const & manager,OString const & type,OString const & delegate)735 void generateDocumentation(std::ostream & o,
736     ProgramOptions const & options, TypeManager const & manager,
737     OString const & type, OString const & delegate)
738 {
739     if (type.indexOf('/') >= 0)
740         throw CannotDumpException("Illegal type name " + type);
741 
742     OString binType(type.replace('.', '/'));
743     RTTypeClass typeClass;
744     OString name;
745     sal_Int32 rank;
746     std::vector< OString > arguments;
747     codemaker::UnoType::Sort sort = decomposeResolveAndCheck(
748         manager, binType, false, true, true, &typeClass, &name, &rank,
749         &arguments);
750 
751     bool comment=true;
752     if (delegate.getLength() > 0) {
753         if (typeClass != RT_TYPE_INTERFACE &&
754             typeClass != RT_TYPE_SERVICE )
755         {
756             return;
757         }
758         comment=false;
759     }
760 
761     if (comment) {
762         o << "\n// UNO";
763         if (rank > 0) {
764             o << " sequence type";
765         } else if (sort != codemaker::UnoType::SORT_COMPLEX) {
766             o << " simple type";
767         } else {
768             typereg::Reader reader(manager.getTypeReader(name));
769             if (!reader.isValid())
770                 throw CannotDumpException("Bad type library entity " + name);
771 
772             switch (typeClass)
773             {
774             case RT_TYPE_INTERFACE:
775                 o << " interface type";
776                 break;
777 
778             case RT_TYPE_MODULE:
779                 o << "IDL module";
780                 break;
781 
782             case RT_TYPE_STRUCT:
783                 if (reader.getReferenceCount() == 0)
784                     o << " simple struct type";
785                 else if (arguments.empty())
786                     o << " polymorphic struct type template";
787                 else
788                     o << " instantiated polymorphic struct type";
789                 break;
790 
791             case RT_TYPE_ENUM:
792                 o << " enum type";
793                 break;
794 
795             case RT_TYPE_EXCEPTION:
796                 o << " exception type";
797                 break;
798 
799             case RT_TYPE_TYPEDEF:
800                 o << "IDL typedef";
801                 break;
802 
803             case RT_TYPE_SERVICE:
804                 if (reader.getSuperTypeCount() > 0)
805                     o << " single-inheritance--based service";
806                 else
807                     o << "IDL accumulation-based service";
808                 break;
809 
810             case RT_TYPE_SINGLETON:
811                 if ((manager.getTypeReader(
812                          codemaker::convertString(
813                              reader.getSuperTypeName(0))).getTypeClass())
814                     == RT_TYPE_INTERFACE)
815                     o << " inheritance-based singleton";
816                 else
817                     o << "IDL service-based singleton";
818                 break;
819 
820             case RT_TYPE_CONSTANTS:
821                 o << "IDL constant group";
822                 break;
823 
824             default:
825                 OSL_ASSERT(false);
826                 break;
827             }
828         }
829         o << " \"" << type.getStr() << "\" ";
830     }
831     sort = codemaker::decomposeAndResolve(
832         manager, binType, true, true, true, &typeClass, &name, &rank,
833         &arguments);
834     if (rank > 0) {
835         if (comment) {
836             printMapsToCppType(o,
837                 options, manager, sort, typeClass, name, rank, arguments, "array");
838             o << '\n';
839         }
840     } else if (sort != codemaker::UnoType::SORT_COMPLEX) {
841         if (comment) {
842             printMapsToCppType(o,
843                 options, manager, sort, typeClass, name, rank, arguments, 0);
844             o << '\n';
845         }
846     } else {
847         typereg::Reader reader(manager.getTypeReader(name));
848         if (!reader.isValid())
849             throw CannotDumpException("Bad type library entity " + name);
850 
851         switch (typeClass)
852         {
853         case RT_TYPE_INTERFACE:
854             if (comment)
855                 printMapsToCppType(o,
856                     options, manager, sort, typeClass, name, rank, arguments,
857                     "interface");
858             if (name == "com/sun/star/uno/XInterface") {
859                 if (comment)
860                     o << '\n';
861             } else {
862                 if (comment)
863                     o << "; " << (options.all ? "all" : "direct") << " methods:\n";
864 
865                 codemaker::GeneratedTypeSet generated;
866                 printMethods(o, options, manager, reader, generated,
867                              delegate, options.implname, "");
868             }
869             break;
870 
871         case RT_TYPE_MODULE:
872             printMapsToCppType(o,
873                 options, manager, sort, typeClass, name, rank, arguments,
874                 "namespace");
875             o << '\n';
876             break;
877 
878         case RT_TYPE_STRUCT:
879             if (reader.getReferenceCount() == 0) {
880                 printMapsToCppType(o,
881                     options, manager, sort, typeClass, name, rank, arguments,
882                     "class");
883             } else if (arguments.empty()) {
884                 printMapsToCppType(o,
885                     options, manager, sort, typeClass, name, rank, arguments,
886                     options.java5 ? "generic class" : "class");
887             } else {
888                 printMapsToCppType(o,
889                     options, manager, sort, typeClass, name, rank, arguments,
890                     options.java5 ? "generic class instantiation" : "class");
891             }
892             o << "; full constructor:\n";
893             printConstructor(o, options, manager, reader, arguments);
894             break;
895 
896         case RT_TYPE_ENUM:
897             printMapsToCppType(o,
898                 options, manager, sort, typeClass, name, rank, arguments,
899                 "enum");
900             o << '\n';
901             break;
902 
903         case RT_TYPE_CONSTANTS:
904             printMapsToCppType(o,
905                 options, manager, sort, typeClass, name, rank, arguments,
906                 "namespace");
907             o << '\n';
908             break;
909 
910         case RT_TYPE_EXCEPTION:
911             printMapsToCppType(o,
912                 options, manager, sort, typeClass, name, rank, arguments,
913                 "exception class");
914             o << "; full constructor:\n";
915             printConstructor(o, options, manager, reader, arguments);
916             break;
917 
918         case RT_TYPE_SERVICE:
919             if (reader.getSuperTypeCount() > 0) {
920                 if (comment) {
921                     printMapsToCppType(o, options, manager, sort, typeClass,
922                                        name, rank, arguments, "class");
923                     o << "; construction methods:\n";
924                     printConstructionMethods(o, options, manager, reader);
925                 }
926 
927                 OString super(
928                     codemaker::convertString(
929                         reader.getSuperTypeName(0)).replace('/', '.'));
930                 generateDocumentation(o, options, manager, super, delegate);
931             } else {
932                 if (comment)
933                     o << ("does not map to C++\n"
934                           "// the service members are generated instead\n");
935                 printServiceMembers(o, options, manager, reader, type, delegate);
936             }
937             break;
938 
939         case RT_TYPE_SINGLETON:
940             if (reader.getSuperTypeCount() > 0 &&
941                 ((manager.getTypeReader(
942                      codemaker::convertString(
943                          reader.getSuperTypeName(0))).
944                     getTypeClass()) == RT_TYPE_INTERFACE) )
945             {
946                 printMapsToCppType(o, options, manager, sort, typeClass,
947                                    name, rank, arguments,
948                     "class");
949                 o << "; get method:\nstatic ";
950                 printType(o, options, manager,
951                           codemaker::convertString(reader.getSuperTypeName(0)), 1);
952                 o << " get(::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext > const & context);\n";
953             } else {
954                 o << "does not map to C++\n";
955             }
956             break;
957 
958         default:
959             OSL_ASSERT(false);
960             break;
961         }
962     }
963 }
964 
965 } }
966 
967 
968