1 #***************************************************************************
2 # kalyptusCxxToKimono.pm - Generates *.cs files for a Custom RealProxy
5 # begin : Thurs Feb 19 12:00:00 2004
6 # copyright : (C) 2004, Richard Dale. All Rights Reserved.
7 # email : Richard_Dale@tipitina.demon.co.uk
8 # author : Richard Dale, based on the SMOKE generation code
9 #***************************************************************************/
11 #/***************************************************************************
13 # * This program is free software; you can redistribute it and/or modify *
14 # * it under the terms of the GNU General Public License as published by *
15 # * the Free Software Foundation; either version 2 of the License, or *
16 # * (at your option) any later version. *
18 #***************************************************************************/
20 package kalyptusCxxToKimono
;
36 $libname $rootnode $outputdir $opt $debug
38 %builtins %typeunion %allMethods %allTypes %enumValueToType %typedeflist %maptypeslist %arraytypeslist %mungedTypeMap %csharpImports
39 %skippedClasses %excludeClasses %partial_classes %operatorNames %new_classidx %interfacemap %iterator_interfacemap *CLASS
/;
44 # Types supported by the StackItem union
45 # Key: C++ type Value: Union field of that type
52 'ushort' => 's_ushort',
58 'double' => 's_double',
63 # Mapping for iterproto, when making up the munged method names
71 'QDBusObjectPath' => '$',
72 'QDBusObjectPath*' => '$',
73 'QDBusObjectPath&' => '$',
74 'QDBusSignature' => '$',
75 'QDBusSignature*' => '$',
76 'QDBusSignature&' => '$',
89 'KMimeType::Ptr' => '#',
90 'KMimeType::Ptr&' => '#',
91 'KServiceGroup::Ptr' => '#',
92 'KServiceGroup::Ptr&' => '#',
93 'KService::Ptr' => '#',
94 'KService::Ptr&' => '#',
95 'KServiceType::Ptr' => '#',
96 'KServiceType::Ptr&' => '#',
97 'KSharedConfig::Ptr' => '#',
98 'KSharedConfig::Ptr&' => '#',
99 'KSharedConfigPtr' => '#',
100 'KSharedConfigPtr&' => '#',
101 'KSharedPtr<KConfigBackend>' => '#',
102 'KSharedPtr<KConfigBackend>&' => '#',
103 'KSycocaEntry::Ptr' => '#',
104 'KSycocaEntry::Ptr&' => '#',
105 'Plasma::PackageStructure::Ptr' => '#',
106 'Plasma::PackageStructure::Ptr&' => '#',
109 # Yes some of this is in kalyptusDataDict's ctypemap
110 # but that one would need to be separated (builtins vs normal classes)
116 'ksocklen_t' => 'uint',
121 'QImageReader::ImageReaderError' => 'int',
123 'Q_INT16' => 'short',
132 'Qt::HANDLE' => 'uint',
134 'Qt::WFlags' => 'uint',
135 'Qt::WState' => 'int',
136 'quint16' => 'ushort',
137 'Q_UINT16' => 'ushort',
139 'Q_UINT32' => 'uint',
140 'quint8' => 'ushort',
141 'Q_UINT8' => 'ushort',
143 'short int' => 'short',
144 'signed char' => 'char',
146 'signed int' => 'int',
147 'signed long int' => 'long',
148 'signed long' => 'long',
149 'signed short' => 'short',
151 'size_type' => 'int', # QSqlRecordInfo
153 'unsigned char' => 'ushort',
154 'unsigned int' => 'uint',
155 'unsigned long int' => 'ulong',
156 'unsigned long' => 'ulong',
157 'unsigned short int' => 'ushort',
158 'unsigned short' => 'ushort',
159 'unsigned' => 'uint',
160 'void(* )()' => 'void*',
161 'void (*)(void* )' => 'void*',
163 'Plasma::PackageStructure::Ptr' => 'Plasma.PackageStructure',
164 'KService::Ptr' => 'KService',
165 'KSharedConfig::Ptr' => 'KSharedConfig',
166 'KSharedConfigPtr' => 'KSharedConfig',
168 'Plasma::Phase::AnimId' => 'int',
169 'KIO::filesize_t' => 'long'
172 # Some classes need extra info in addition to the autogenerated code.
173 # So they are split into two sources FooBar.cs and FooBarExtras.cs
174 # with the 'partial' modifier in the class definition
177 'KConfigGroup' => '1',
178 'KCmdLineArgs' => '1',
179 'QAbstractItemModel' => '1',
180 'QApplication' => '1',
184 'QCoreApplication' => '1',
186 'QDBusConnectionInterface' => '1',
188 'QKeySequence' => '1',
190 'QModelIndex' => '1',
199 'QSqlQueryModel' => '1',
200 'QStringListModel' => '1',
209 'operator^' => 'op_xor',
210 'operator^=' => 'op_xor_assign',
211 'operator<' => 'op_lt',
212 'operator<<' => 'Write',
213 'operator<=' => 'op_lte',
214 'operator=' => 'op_assign',
215 'operator==' => 'op_equals',
216 'operator>' => 'op_gt',
217 'operator>=' => 'op_gte',
218 'operator>>' => 'Read',
219 'operator|' => 'op_or',
220 'operator|=' => 'op_or_assign',
221 'operator-' => 'op_minus',
222 'operator-=' => 'op_minus_assign',
223 'operator--' => 'op_decr',
224 'operator!' => 'op_not',
225 'operator!=' => 'op_not_equals',
226 'operator/' => 'op_div',
227 'operator/=' => 'op_div_assign',
228 'operator()' => 'op_expr',
229 'operator[]' => 'op_at',
230 'operator*' => 'op_mult',
231 'operator*=' => 'op_mult_assign',
232 'operator&' => 'op_and',
233 'operator&=' => 'op_and_assign',
234 'operator+' => 'op_plus',
235 'operator+=' => 'op_plus_assign',
236 'operator++' => 'op_incr',
241 'QMap<int, QVariant>' => 'Dictionary<int, QVariant>',
242 'QMap<int, QVariant>&' => 'Dictionary<int, QVariant>',
243 'QMap<QDate, QTextCharFormat>' => 'Dictionary<QDate, QTextCharFormat>',
244 'QMap<QDate, QTextCharFormat>&' => 'Dictionary<QDate, QTextCharFormat>',
245 'QMap<QString, QString>' => 'Dictionary<string, string>',
246 'QMap<QString, QString>&' => 'Dictionary<string, string>',
247 'QMap<QString, QVariant>' => 'Dictionary<string, QVariant>',
248 'QMap<QString, QVariant>&' => 'Dictionary<string, QVariant>',
249 'QMap<QString, int>&' => 'Dictionary<string, int>',
250 'QVariantMap&' => 'Dictionary<string, QVariant>',
251 'QMap<QString, QVariant::Type>' => 'Dictionary<string, QVariant.TypeOf>',
252 'Plasma::DataEngine::Data' => 'Dictionary<string, QVariant>',
253 'Plasma::DataEngine::Data&' => 'Dictionary<string, QVariant>',
254 'QHash<QString, DataContainer*>' => 'Dictionary<string, Plasma.DataContainer>',
255 'QHash<QUrl, Nepomuk::Variant>' => 'Dictionary<QUrl, Nepomuk.Variant>',
256 'Plasma::DataEngine::SourceDict' => 'Dictionary<string, Plasma.DataContainer>',
261 'Akonadi::AgentInstance::List' => 'List<Akonadi.AgentInstance>',
262 'Akonadi::AgentType::List' => 'List<Akonadi.AgentType>',
263 'Akonadi::Attribute::List' => 'List<Akonadi.Attribute>',
264 'Akonadi::Collection::List' => 'List<Akonadi.Collection>',
265 'Akonadi::Collection::List&' => 'List<Akonadi.Collection>',
266 'Akonadi::Item::List' => 'List<Akonadi.Item>',
267 'Akonadi::Item::List&' => 'List<Akonadi.Item>',
268 'Akonadi::Job::List' => 'List<Akonadi.Job>',
269 'Akonadi::Job::List&' => 'List<Akonadi.Job>',
270 'KCompletionMatches' => 'List<string>',
271 'KCompletionMatches*' => 'List<string>',
272 'KCompletionMatchesList' => 'List<List<string>>',
273 'KCompletionMatchesList&' => 'List<List<string>>',
274 'KCompletionMatchesList*' => 'List<List<string>>',
275 'KFileItemList' => 'List<KFileItem>',
276 'KFileItemList*' => 'List<KFileItem>',
277 'KFileItemList&' => 'List<KFileItem>',
278 'KNS::Entry::List' => 'List<KNS.Entry>',
279 'KPluginInfo::List' => 'List<KPluginInfo>',
280 'KService::List' => 'List<KService>',
281 'KServiceOfferList' => 'List<KServiceOffer>',
282 'KUrl::List' => 'List<KUrl>',
283 'KUrl::List*' => 'List<KUrl>',
284 'KUrl::List&' => 'List<KUrl>',
285 'KUrlList' => 'List<KUrl>',
286 'KUrlList&' => 'List<KUrl>',
287 'QFileInfoList' => 'List<QFileInfo>',
288 'QFileInfoList&' => 'List<QFileInfo>',
289 'QList<const char*>' => 'List<string>',
290 'QList<const char*>&' => 'List<string>',
291 'QList<double>' => 'List<double>',
292 'QList<double>&' => 'List<double>',
293 'QList<int>' => 'List<int>',
294 'QList<int>&' => 'List<int>',
295 'QList<uint>' => 'List<uint>',
296 'QList<uint>&' => 'List<uint>',
297 'QList<KAboutPerson>' => 'List<KAboutPerson>',
298 'QList<KAboutTranslator>' => 'List<KAboutTranslator>',
299 'QList<KActionCollection*>&' => 'List<KActionCollection>',
300 'QList<KAction*>' => 'List<KAction>',
301 'QList<KConfigDialogManager*>&' => 'List<KConfigDialogManager>',
302 'QList<KConfigSkeleton::ItemEnum::Choice>' => 'List<KConfigSkeleton.ItemEnum.Choice>',
303 'QList<KConfigSkeleton::ItemEnum::Choice>&' => 'List<KConfigSkeleton.ItemEnum.Choice>',
304 'QList<Choice>' => 'List<KConfigSkeleton.ItemEnum.Choice>',
305 'QList<Choice>&' => 'List<KConfigSkeleton.ItemEnum.Choice>',
306 'QList<KDataToolInfo>' => 'List<KDataToolInfo>',
307 'QList<KDataToolInfo>&' => 'List<KDataToolInfo>',
308 'QList<KConfigDialogManager*>' => 'List<KConfigDialogManager>',
309 'QList<KFileItem>' => 'List<KFileItem>',
310 'QList<KFileItem>&' => 'List<KFileItem>',
311 # 'QList<KIO::CopyInfo>&' => 'List<KIO.CopyInfo>',
312 'QList<KJob*>&' => 'List<KJob>',
313 'QList<KMainWindow*>' => 'List<KMainWindow>',
314 'QList<KMainWindow*>&' => 'List<KMainWindow>',
315 'QList<KMultiTabBarButton*>' => 'List<KMultiTabBarButton>',
316 'QList<KMultiTabBarTab*>' => 'List<KMultiTabBarTab>',
317 'QList<KParts::Part*>' => 'List<KParts.Part>',
318 'QList<KParts::Plugin*>' => 'List<KParts.Plugin>',
319 # 'QList<KParts::Plugin::PluginInfo>' => 'List<QXmlStreamNotationDeclaration>',
320 # 'QList<KParts::Plugin::PluginInfo>&' => 'List<QXmlStreamNotationDeclaration>',
321 'QList<KParts::ReadOnlyPart*>' => 'List<KParts.ReadOnlyPart>',
322 'QList<KPluginInfo>' => 'List<KPluginInfo>',
323 'QList<KPluginInfo>&' => 'List<KPluginInfo>',
324 'QList<KServiceOffer>&' => 'List<KServiceOffer>',
325 'QList<KSSLCertificate*>&' => 'List<KSSLCertificate>',
326 'QList<KToolBar*>' => 'List<KToolBar>',
327 'QList<KUrl>' => 'List<KUrl>',
328 'QList<KUrl>&' => 'List<KUrl>',
329 'QList<KUserGroup>' => 'List<KUserGroup>',
330 'QList<KUser>' => 'List<KUser>',
331 'QList<KUser>&' => 'List<KUser>',
332 'QList<KXMLGUIClient*>' => 'List<KXMLGUIClient>',
333 'QList<KXMLGUIClient*>&' => 'List<KXMLGUIClient>',
334 'QList<Plasma::Containment*>' => 'List<Plasma.Containment>',
335 'QList<Plasma::Containment*>&' => 'List<Plasma.Containment>',
336 'QList<Plasma::PlotColor>' => 'List<Plasma.PlotColor>',
337 'QList<Plasma::PlotColor>&' => 'List<Plasma.PlotColor>',
338 'QList<Plasma::SearchMatch*>' => 'List<Plasma.SearchMatch>',
339 'QList<Plasma::SearchMatch*>&' => 'List<Plasma.SearchMatch>',
340 'QList<Plasma::QueryMatch>' => 'List<Plasma.QueryMatch>',
341 'QList<Plasma::QueryMatch>&' => 'List<Plasma.QueryMatch>',
342 'Plasma::Applet::List' => 'List<Plasma.Applet>',
343 'Plasma::AbstractRunner::List' => 'List<Plasma.AbstractRunner>',
344 'QList<QAbstractButton*>' => 'List<QAbstractButton>',
345 'QList<QActionGroup*>' => 'List<QAction>',
346 'QList<QAction*>' => 'List<QAction>',
347 'QList<QAction*>&' => 'List<QAction>',
348 'QList<QByteArray>' => 'List<QByteArray>',
349 'QList<QByteArray>*' => 'List<QByteArray>',
350 'QList<QByteArray>&' => 'List<QByteArray>',
351 'QList<QGraphicsItem*>' => 'List<QGraphicsItem>',
352 'QList<QGraphicsItem*>&' => 'List<QGraphicsItem>',
353 'QList<QGraphicsView*>' => 'List<QGraphicsView>',
354 'QList <QGraphicsView*>' => 'List<QGraphicsView>',
355 'QList<QHostAddress>' => 'List<QHostAddress>',
356 'QList<QHostAddress>&' => 'List<QHostAddress>',
357 # 'QList<QImageTextKeyLang>' => 'List<QImageTextKeyLang>',
358 'QList<QKeySequence>' => 'List<QKeySequence>',
359 'QList<QKeySequence>&' => 'List<QKeySequence>',
360 'QList<QListWidgetItem*>' => 'List<QListWidgetItem>',
361 'QList<QListWidgetItem*>&' => 'List<QListWidgetItem>',
362 'QList<QLocale::Country>' => 'List<QLocale.Country>',
363 'QList<QMdiSubWindow*>' => 'List<QMdiSubWindow>',
364 'QList<QModelIndex>' => 'List<QModelIndex>',
365 'QList<QModelIndex>&' => 'List<QModelIndex>',
366 'QList<QNetworkAddressEntry>' => 'List<QNetworkAddressEntry>',
367 'QList<QNetworkCookie>' => 'List<QNetworkCookie>',
368 'QList<QNetworkCookie>&' => 'List<QNetworkCookie>',
369 'QList<QNetworkInterface>' => 'List<QNetworkInterface>',
370 # These List types with doubles don't compile:
371 # 'QList<QPair<qreal, QPointF> >' => 'List<double, QPointF>',
372 'QList<QPair<qreal, QPointF> >' => 'List<QPair<double, QPointF>>',
373 'QList<QPair<qreal, qreal> >' => 'List<QPair<double, double>>',
374 # 'QList<QPair<qreal, qreal> >' => 'List<QPair<double, double>>',
375 'QList<QPair<QString, QString> >' => 'List<QPair<string, string>>',
376 'QList<QPair<QString, QString> >&' => 'List<QPair<string, string>>',
377 'QList<QPixmap>' => 'List<QPixmap>',
378 'QList<QPolygonF>' => 'List<QPolygonF>',
379 'QList<QPrinterInfo>' => 'List<QPrinterInfo>',
380 'QList<qreal>' => 'List<double>',
381 'QList<QRectF>' => 'List<QRectF>',
382 'QList<QRectF>&' => 'List<QRectF>',
383 'QList<QSslCertificate>' => 'List<QSslCertificate>',
384 'QList<QSslCertificate>&' => 'List<QSslCertificate>',
385 'QList<QSslCipher>' => 'List<QSslCipher>',
386 'QList<QSslCipher>&' => 'List<QSslCipher>',
387 'QList<QSslError>' => 'List<QSslError>',
388 'QList<QSslError>&' => 'List<QSslError>',
389 'QList<QStandardItem*>' => 'List<QStandardItem>',
390 'QList<QStandardItem*>&' => 'List<QStandardItem>',
391 'QList<QStringList>' => 'List<List<string>>',
392 'QList<QTableWidgetItem*>' => 'List<QTableWidgetItem>',
393 'QList<QTableWidgetItem*>&' => 'List<QTableWidgetItem>',
394 'QList<QTableWidgetSelectionRange>' => 'List<QTableWidgetSelectionRange>',
395 'QList<QTextBlock>' => 'List<QTextBlock>',
396 'QList<QTextFrame*>' => 'List<QTextFrame>',
397 # 'QList<QTextLayout::FormatRange>' => 'List<QTextLayout.FormatRange>',
398 # 'QList<QTextLayout::FormatRange>&' => 'List<QTextLayout.FormatRange>',
399 'QList<QTreeWidgetItem*>' => 'List<QTreeWidgetItem>',
400 'QList<QTreeWidgetItem*>&' => 'List<QTreeWidgetItem>',
401 'QList<QTreeWidget*>' => 'List<QTreeWidget>',
402 'QList<QTreeWidget*>&' => 'List<QTreeWidget>',
403 'QList<QUndoStack*>' => 'List<QUndoStack>',
404 'QList<QUndoStack*>&' => 'List<QUndoStack>',
405 'QList<QUrl>' => 'List<QUrl>',
406 'QList<QUrl>&' => 'List<QUrl>',
407 'QList<QVariant>' => 'List<QVariant>',
408 'QList<QVariant>&' => 'List<QVariant>',
409 'QList<QWidget*>' => 'List<QWidget>',
410 'QList<QWidget*>&' => 'List<QWidget>',
411 'QList<QWebFrame*>' => 'List<QWebFrame>',
412 'QList<QWebHistoryItem>' => 'List<QWebHistoryItem>',
413 'QList<QWizard::WizardButton>&' => 'List<QWizard.WizardButton>',
414 'QModelIndexList' => 'List<QModelIndex>',
415 'QModelIndexList&' => 'List<QModelIndex>',
416 'QObjectList' => 'List<QObject>',
417 'QObjectList&' => 'List<QObject>',
418 'QStringList' => 'List<string>',
419 'QStringList*' => 'List<string>',
420 'QStringList&' => 'List<string>',
421 'QVariantList' => 'List<QVariant>',
422 'QVariantList*' => 'List<QVariant>',
423 'QVariantList&' => 'List<QVariant>',
424 'QVector<QAbstractTextDocumentLayout::Selection>' => 'List<QAbstractTextDocumentLayout.Selection>',
425 'QVector<Selection>' => 'List<QAbstractTextDocumentLayout.Selection>',
426 'QVector<QColor>' => 'List<QColor>',
427 'QVector<QColor>&' => 'List<QColor>',
428 'QVector<QLineF>' => 'List<QLineF>',
429 'QVector<QLineF>&' => 'List<QLineF>',
430 'QVector<QLine>' => 'List<QLine>',
431 'QVector<QLine>&' => 'List<QLine>',
432 'QVector<QPointF>' => 'List<QPointF>',
433 'QVector<QPointF>&' => 'List<QPointF>',
434 'QVector<QPoint>' => 'List<QPoint>',
435 'QVector<QPoint>&' => 'List<QPoint>',
436 'QVector<qreal>' => 'List<double>',
437 'QVector<qreal>&' => 'List<double>',
438 'QVector<QRectF>' => 'List<QRectF>',
439 'QVector<QRectF>&' => 'List<QRectF>',
440 'QVector<QRect>' => 'List<QRect>',
441 'QVector<QRect>&' => 'List<QRect>',
442 'QVector<QRgb>' => 'List<uint>',
443 'QVector<QRgb>&' => 'List<uint>',
444 'QVector<QTextFormat>' => 'List<QTextFormat>',
445 'QVector<QTextFormat>&' => 'List<QTextFormat>',
446 'QVector<QTextLength>' => 'List<QTextLength>',
447 'QVector<QTextLength>&' => 'List<QTextLength>',
448 'QVector<QVariant>' => 'List<QVariant>',
449 'QVector<QVariant>&' => 'List<QVariant>',
450 'QWidgetList' => 'List<QWidget>',
451 'QWidgetList&' => 'List<QWidget>',
452 'QXmlStreamEntityDeclarations' => 'List<QXmlStreamEntityDeclaration>',
453 'QXmlStreamNamespaceDeclarations' => 'List<QXmlStreamNamespaceDeclaration>',
454 'QXmlStreamNotationDeclarations' => 'List<QXmlStreamNotationDeclaration>',
458 'KBookmarkActionInterface' => 'IKBookmarkAction',
459 'KCompletionBase' => 'IKCompletionBase',
460 'KDevCore' => 'IKDevCore',
461 'KDirNotify' => 'IKDirNotify',
462 'KFileView' => 'IKFileView',
463 'KIO.SlaveBase' => 'KIO.ISlaveBase',
464 'KMessageHandler' => 'IKMessageHandler',
465 'KParts.PartBase' => 'KParts.IPartBase',
466 'KXMLGUIBuilder' => 'IKXMLGUIBuilder',
467 'KXMLGUIClient' => 'IKXMLGUIClient',
468 'PartBase' => 'IPartBase',
469 'QGraphicsItem' => 'IQGraphicsItem',
470 'QGraphicsLayoutItem' => 'IQGraphicsLayoutItem',
471 'QLayoutItem' => 'IQLayoutItem',
472 'QMimeSource' => 'IQMimeSource',
473 'QPaintDevice' => 'IQPaintDevice',
474 'QwAbsSpriteFieldView' => 'IQwAbsSpriteFieldView',
475 'QwtAbstractScale' => 'IQwtAbstractScale',
476 'QwtDoubleRange' => 'IQwtDoubleRange',
477 'QwtEventPattern' => 'IQwtEventPattern',
478 'QwtPlotDict' => 'IQwtPlotDict',
479 'QXmlContentHandler' => 'IQXmlContentHandler',
480 'QXmlDeclHandler' => 'IQXmlDeclHandler',
481 'QXmlDTDHandler' => 'IQXmlDTDHandler',
482 'QXmlEntityResolver' => 'IQXmlEntityResolver',
483 'QXmlErrorHandler' => 'IQXmlErrorHandler',
484 'SlaveBase' => 'ISlaveBase',
485 'Soprano.Error.ErrorCache' => 'Soprano.Error.IErrorCache',
486 'ErrorCache' => 'IErrorCache',
489 # Mono 1.2.4 doesn't seem to compile IEnumerable classes, so comment these
491 %iterator_interfacemap = (
492 # 'Soprano::QueryResultIterator' => 'IEnumerable<Soprano.BindingSet>',
493 # 'Soprano::StatementIterator' => 'IEnumerable<Soprano.Statement>',
494 # 'Soprano::NodeIterator' => 'IEnumerable<Soprano.Node>',
495 # 'Soprano::DBusQueryResultIterator' => 'IEnumerable<Soprano.BindingSet>',
496 # 'Soprano::DBusStatementIterator' => 'IEnumerable<Soprano.Statement>',
497 # 'Soprano::DBusNodeIterator' => 'IEnumerable<Soprano.Node>',
504 my ( $classname ) = @_;
505 my $classname_ptr = $classname . "*";
506 if ( cplusplusToCSharp
($classname_ptr) eq "" or $classname eq $main::globalSpaceClassName
) {
508 } elsif ( cplusplusToCSharp
($classname_ptr) eq "ArrayList" ) {
509 return "System.Collections";
510 } elsif ( cplusplusToCSharp
($classname_ptr) =~ /^List</ ) {
511 return "System.Collections.Generic";
512 } elsif ( cplusplusToCSharp
($classname_ptr) eq "StringBuilder" ) {
514 } elsif ( cplusplusToCSharp
($classname_ptr) eq "string" ) {
516 } elsif ( cplusplusToCSharp
($classname_ptr) eq "string[][]" ) {
518 # } elsif ( cplusplusToCSharp($classname_ptr) eq "string[]" ) {
520 } elsif ( cplusplusToCSharp
($classname_ptr) =~ /^[a-z]/ ) {
526 sub cplusplusToCSharp
528 my ( $cplusplusType ) = @_;
529 my $isConst = ($cplusplusType =~ /const / or $cplusplusType !~ /[*&]/ ?
1 : 0);
530 $cplusplusType =~ s/const //;
531 $cplusplusType =~ s/^signed//;
532 my $className = $cplusplusType;
533 $className =~ s/[*&]//;
535 if ( $cplusplusType =~ /void\*|KDateTime::Spec&?$|K3Icon|KHTMLPart::PageSecurity|EditMode|QNetworkProtocolFactoryBase|QDomNodePrivate|QSqlDriverCreatorBase|QSqlFieldInfoList|QObjectUserData|QUObject|QTextParag|QWidgetMapper|QMemArray<int>|QLayoutIterator|QAuBucket|QUnknownInterface|QConnectionList/ ) {
536 return ""; # Unsupported type
537 } elsif ( $cplusplusType =~ /bool/ && kalyptusDataDict
::ctypemap
($cplusplusType) eq "int" ) {
539 } elsif ( $cplusplusType =~ /bool\s*[*&]/ ) {
542 } elsif ( $cplusplusType =~ /^long$|^qint64$/) {
544 } elsif ( $cplusplusType =~ /^ulong$|^quint64$/) {
546 } elsif ( $cplusplusType eq 'qlonglong') {
548 } elsif ( $cplusplusType eq 'qulonglong') {
550 } elsif ( $cplusplusType =~ /^QPair<(.*), (.*)>/) {
551 my $generic1 = cplusplusToCSharp
($1);
552 my $generic2 = cplusplusToCSharp
($2);
553 return '' if ($generic1 eq '' || $generic2 eq '');
554 return "QPair<$generic2, $generic1>";
555 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^void\s*\*/ ) {
557 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^qt_QIntValueList\*/ )
560 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^\s*(unsigned )?int\s*\*/
561 || $cplusplusType =~ /^int[*&]$/ )
565 } elsif ( $cplusplusType =~ /qreal[*&]$/ )
569 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^\s*double\s*\*/ ) {
572 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^\s*(unsigned )?short\s*\*/ ) {
575 } elsif ( $maptypeslist{$cplusplusType} ) {
576 return $maptypeslist{$cplusplusType};
577 } elsif ( $arraytypeslist{$cplusplusType} ) {
578 return $arraytypeslist{$cplusplusType};
579 } elsif ( $typedeflist{$cplusplusType} ) {
580 return $typedeflist{$cplusplusType};
581 } elsif ( $cplusplusType =~ /^QList<(.*)>/ ) {
582 my $generic = cplusplusToCSharp
($1);
583 return '' if ($generic eq '');
584 return "List<$generic>";
585 } elsif ( $cplusplusType =~ /^QVector<(.*)>/ ) {
586 my $generic = cplusplusToCSharp
($1);
587 return '' if ($generic eq '');
588 return "List<$generic>";
589 } elsif ( $cplusplusType =~ /uchar\s*\*/ ) {
591 } elsif ( $cplusplusType =~ /uchar/ ) {
593 } elsif ( $cplusplusType =~ /QC?String/ and !$isConst ) {
594 return "StringBuilder"
595 } elsif ( $cplusplusType =~ /^[^<]*QString/
596 || $cplusplusType =~ /QCString/
597 || $cplusplusType =~ /^(const )?char\s*\*$/
598 || kalyptusDataDict
::ctypemap
($cplusplusType) =~ /^(const )?char\s*\*/ ) {
600 # } elsif ( $cplusplusType =~ /QChar\s*[&\*]?/ || $cplusplusType =~ /^char$/ ) {
602 } elsif ( $cplusplusType =~ /QDBusObjectPath/ ) {
603 return "QDBusObjectPath"
604 } elsif ( $cplusplusType =~ /QDBusSignature/ ) {
605 return "QDBusSignature"
606 } elsif ( $cplusplusType =~ /QDBusVariant/ ) {
607 return "QDBusVariant"
608 } elsif ( $cplusplusType =~ /QPaintDevice/ ) {
609 return "IQPaintDevice"
610 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /unsigned char/ ) {
612 } elsif ( $typedeflist{$cplusplusType} =~ /ulong/ || $cplusplusType eq 'ulong' ) {
614 } elsif ( $typedeflist{$cplusplusType} =~ /long/ || $cplusplusType eq 'long' ) {
616 } elsif ( $typedeflist{$cplusplusType} =~ /uint/ || $cplusplusType eq 'uint' ) {
618 } elsif ( $typedeflist{$cplusplusType} =~ /int/ || $cplusplusType eq 'int' ) {
620 } elsif ( $typedeflist{$cplusplusType} =~ /ushort/ || $cplusplusType eq 'ushort' ) {
622 } elsif ( $typedeflist{$cplusplusType} =~ /short/ || $cplusplusType eq 'short') {
624 } elsif ( $typedeflist{$cplusplusType} =~ /float/ || $cplusplusType eq 'float' ) {
626 } elsif ( $typedeflist{$cplusplusType} =~ /double/ || $cplusplusType eq 'double') {
628 } elsif ( kalyptusDataDict
::ctypemap
($cplusplusType) =~ /(unsigned )(.*)/ ) {
633 if ($className =~ /^(\w+)::(\w+)::(\w+)::(\w+)$/) {
634 $node = kdocAstUtil
::findRef
( $rootnode, $1 );
636 $node = kdocAstUtil
::findRef
( $node, $2 );
638 $node = kdocAstUtil
::findRef
( $node, $3 );
639 $item = kdocAstUtil
::findRef
( $node, $4 ) if defined $node;
640 if (defined $item && $item->{NodeType
} eq 'enum') {
642 return "$1.$2.$3.TypeOf";
644 return "$1.$2.$3.$4";
646 } elsif (defined $item && ($item->{NodeType
} eq 'class' || $item->{NodeType
} eq 'struct')) {
647 return $skippedClasses{$className} ?
"" : "$1.$2.$3.$4";
651 } elsif ($className =~ /^(\w+)::(\w+)::(\w+)$/) {
652 $node = kdocAstUtil
::findRef
( $rootnode, $1 );
654 $node = kdocAstUtil
::findRef
( $node, $2 );
655 $item = kdocAstUtil
::findRef
( $node, $3 ) if defined $node;
656 if (defined $item && $item->{NodeType
} eq 'enum') {
658 return "$1.$2.TypeOf";
662 } elsif (defined $item && ($item->{NodeType
} eq 'class' || $item->{NodeType
} eq 'struct')) {
663 return $skippedClasses{$className} ?
"" : "$1.$2.$3";
666 } elsif ($className =~ /^(\w+)::(\w+)$/) {
667 $node = kdocAstUtil
::findRef
( $rootnode, $1 );
668 $item = kdocAstUtil
::findRef
( $node, $2 ) if defined $node;
669 if (defined $item && $item->{NodeType
} eq 'enum') {
675 } elsif (defined $item && ($item->{NodeType
} eq 'class' || $item->{NodeType
} eq 'struct')) {
676 return $skippedClasses{$className} ?
"" : "$1.$2";
680 if ($className =~ /^\w+$/) {
681 $item = kdocAstUtil
::findRef
( $rootnode, $className );
682 if (defined $item && ($item->{NodeType
} eq 'class' || $item->{NodeType
} eq 'struct')) {
683 return $skippedClasses{$className} ?
"" : $className;
686 return kalyptusDataDict
::ctypemap
($cplusplusType);;
693 ( $libname, $rootnode, $outputdir, $opt ) = @_;
695 print STDERR
"Starting writeDoc for $libname...\n";
697 # if no classlist is given, process all classes
698 if ($main::classlist
) {
700 open DAT
, "$main::classlist";
701 foreach my $class (<DAT
>) {
703 $includeClasses{$class} = 1;
707 Iter
::LocalCompounds
( $rootnode, sub {
708 my $classNode = shift;
709 my $className = join( '::', kdocAstUtil
::heritage
($classNode) );
710 $excludeClasses{$className} = 1 unless defined $includeClasses{$className};
714 $debug = $main::debuggen
;
716 if (!$main::smokeInvocation
) {
717 $main::smokeInvocation
= "SmokeInvocation"
720 mkpath
( $outputdir ) unless -f
$outputdir;
722 print STDERR
"Preparsing...\n";
725 Iter
::LocalCompounds
( $rootnode, sub { preParseFlags
( shift ); } );
727 # Preparse everything, to prepare some additional data in the classes and methods
728 Iter
::LocalCompounds
( $rootnode, sub { preParseClass
( shift ); } );
730 # Have a look at each class again, to propagate CanBeCopied
731 Iter
::LocalCompounds
( $rootnode, sub { propagateCanBeCopied
( shift ); } );
733 # Write out smokedata.cpp
734 writeSmokeDataFile
($rootnode);
736 print STDERR
"Writing *.cs...\n";
739 push @classlist, ""; # Prepend empty item for "no class"
741 Iter
::LocalCompounds
( $rootnode, sub {
742 my $classNode = $_[0];
743 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
745 return if $classNode->{NodeType
} eq 'namespace';
747 push @classlist, $className;
748 $enumclasslist{$className}++ if keys %{$classNode->{enumerations
}};
749 $classNode->{ClassIndex
} = $#classlist;
750 # addImportForClass( $classNode, \%allImports, undef );
753 %new_classidx = do { my $i = 0; map { $_ => $i++ } @classlist };
755 # Generate *cs file for each class
756 Iter
::LocalCompounds
( $rootnode, sub {
757 my $classNode = $_[0];
758 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
759 return if defined($excludeClasses{$className});
760 writeClassDoc
( shift );
763 print STDERR
"Done.\n";
767 Called for each class, looks for Q_DECLARE_FLAGS, and maps them to uints
771 my( $classNode ) = @_;
772 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
774 Iter
::MembersByType
( $classNode, undef,
776 my( $classNode, $m ) = @_;
778 if ( $m->{NodeType
} eq 'flags' ) {
779 my $fullFlagsName = $className."::".$m->{astNodeName
};
781 if (exists $typedeflist{$fullFlagsName}) {
782 print("typemap for $fullFlagsName exists\n");
785 $typedeflist{$fullFlagsName} = 'uint';
786 registerType
( $fullFlagsName );
793 Called for each class
797 my( $classNode ) = @_;
798 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
800 if ( $classNode->{Deprecated
}
801 || $classNode->{NodeType
} eq 'union'
802 || $#{$classNode->{Kids}} < 0
803 || $classNode->{Access
} eq "private"
804 || $classNode->{Access
} eq "protected" # e.g. QPixmap::QPixmapData
805 || $className =~ /.*Private$/ # Ignore any classes which aren't for public consumption
806 || $className =~ /.*Impl$/
807 || $className =~ /.*Internal.*/
808 || exists $classNode->{Tmpl
}
809 || $className eq 'KAccelGen'
810 || $className eq 'KDateTime::Spec'
811 || $className eq 'KDEDModule'
812 || $className eq 'KDialogButtonBox'
813 || $className eq 'KDirOperator'
814 || $className eq 'KDirSelectDialog'
815 || $className eq 'KEditListBox::CustomEditor'
816 || $className eq 'KFileFilterCombo'
817 || $className eq 'KFileMetaInfo'
818 || $className eq 'KFileMetaInfoGroup'
819 || $className eq 'KFileTreeBranch'
820 || $className eq 'KFileView'
821 || $className eq 'KFileViewSignaler'
822 || $className eq 'KGlobalSettings::KMouseSettings'
823 || $className eq 'khtml'
824 || $className eq 'khtml::DrawContentsEvent'
825 || $className eq 'khtml::MouseDoubleClickEvent'
826 || $className eq 'khtml::MouseEvent'
827 || $className eq 'khtml::MouseMoveEvent'
828 || $className eq 'khtml::MousePressEvent'
829 || $className eq 'khtml::MouseReleaseEvent'
830 || $className eq 'KIconTheme'
831 || $className eq 'KIO::NetRC'
832 || $className eq 'KMimeTypeChooserDialog'
833 || $className eq 'KParts::ComponentFactory'
834 || $className eq 'KParts::Plugin::PluginInfo'
835 || $className eq 'KProtocolInfo::ExtraField'
836 || $className eq 'KServiceTypeProfile'
837 || $className eq 'KSettings::PluginPage'
838 || $className eq 'KTimeZone::Transition'
839 || $className eq 'KTipDatabase'
840 || $className eq 'KTzfileTimeZoneData'
841 || $className eq 'KUrl::List'
842 || $className eq 'KXMLGUIClient::StateChange'
843 || $className eq 'Soprano::Backend'
844 || $className eq 'Soprano::QueryResultIteratorBackend'
845 || $className eq 'Soprano::BackendSetting'
846 || $className eq 'QAbstractTextDocumentLayout::PaintContext'
847 || $className eq 'QAbstractTextDocumentLayout::Selection'
848 || $className eq 'QAbstractUndoItem'
849 || $className eq 'QAccessibleBridgePlugin'
850 || $className eq 'QBrushData'
851 || $className eq 'QDBusObjectPath'
852 || $className eq 'QDBusSignature'
853 || $className eq 'QDBusVariant'
854 || $className eq 'QDebug'
855 || $className eq 'QImageTextKeyLang'
856 || $className eq 'QInputMethodEvent::Attribute'
857 || $className eq 'QIPv6Address'
858 || $className eq 'QLatin1String'
859 || $className eq 'QMap::const_iterator'
860 || $className eq 'QMapData'
861 || $className eq 'QMapData::Node'
862 || $className eq 'QMap::iterator'
863 || $className eq 'QMutex'
864 || $className eq 'QMutexLocker'
865 || $className eq 'QObjectData'
866 || $className eq 'QPainterPath::Element'
867 || $className eq 'QProxyModel'
868 || $className eq 'QReadLocker'
869 || $className eq 'QReadWriteLock'
870 || $className eq 'QSemaphore'
871 || $className eq 'QSharedData'
872 || $className eq 'QString'
873 || $className eq 'QStringList'
874 || $className eq 'QStyleOptionQ3DockWindow'
875 || $className eq 'QStyleOptionQ3ListView'
876 || $className eq 'QStyleOptionQ3ListViewItem'
877 || $className eq 'QSysInfo'
878 || $className eq 'QTextCodec::ConverterState'
879 || $className eq 'QTextLayout::FormatRange'
880 || $className eq 'QTextStreamManipulator'
881 || $className eq 'QThread'
882 || $className eq 'QThreadStorageData'
883 || $className eq 'QUpdateLaterEvent'
884 || $className eq 'QVariant::Handler'
885 || $className eq 'QVariant::PrivateShared'
886 || $className eq 'QVariantComparisonHelper'
887 || $className eq 'QVectorData'
888 || $className eq 'QWaitCondition'
889 || $className eq 'QWidgetData'
890 || $className eq 'QWriteLocker'
891 || $className eq 'QX11Info' )
893 print STDERR
"Skipping $className\n" if ($debug);
894 print STDERR
"Skipping union $className\n" if ( $classNode->{NodeType
} eq 'union');
895 $skippedClasses{$className} = 1;
896 delete $classNode->{Compound
}; # Cheat, to get it excluded from Iter::LocalCompounds
901 my $eventHandlerCount = 0;
902 my $defaultConstructor = 'none'; # none, public, protected or private. 'none' will become 'public'.
903 my $constructorCount = 0; # total count of _all_ ctors
904 # If there are ctors, we need at least one public/protected one to instanciate the class
905 my $hasPublicProtectedConstructor = 0;
906 # We need a public dtor to destroy the object --- ### aren't protected dtors ok too ??
907 my $hasPublicDestructor = 1; # by default all classes have a public dtor!
908 #my $hasVirtualDestructor = 0;
909 my $hasDestructor = 0;
910 my $hasPrivatePureVirtual = 0;
911 my $hasCopyConstructor = 0;
912 my $hasPrivateCopyConstructor = 0;
913 # Note: no need for hasPureVirtuals. $classNode{Pure} has that.
915 if (defined $iterator_interfacemap{$className}) {
916 $partial_classes{$classNode->{astNodeName
}} = 1;
919 my $doPrivate = $main::doPrivate
;
920 $main::doPrivate
= 1;
921 # Look at each class member (looking for methods and enums in particular)
922 Iter
::MembersByType
( $classNode, undef,
925 my( $classNode, $m ) = @_;
926 my $name = $m->{astNodeName
};
928 if( $m->{NodeType
} eq "method" ) {
929 if ( $m->{ReturnType
} eq 'typedef' # QFile's EncoderFn/DecoderFn callback, very badly parsed
931 $m->{NodeType
} = 'deleted';
935 print STDERR
"preParseClass: looking at $className\::$name $m->{Params}\n" if ($debug);
937 if ( $name eq $classNode->{astNodeName
} ) {
938 if ( $m->{ReturnType
} =~ /~/ ) {
940 $hasPublicDestructor = 0 if $m->{Access
} ne 'public';
941 #$hasVirtualDestructor = 1 if ( $m->{Flags} =~ "v" && $m->{Access} ne 'private' );
946 $defaultConstructor = $m->{Access
} if ( $m->{Params
} eq '' );
947 $hasPublicProtectedConstructor = 1 if ( $m->{Access
} ne 'private' );
950 if ( $#{$m->{ParamList}} == 0 ) {
951 my $theArgType = @
{$m->{ParamList
}}[0]->{ArgType
};
952 if ($theArgType =~ /$className\s*\&/) {
953 $hasCopyConstructor = 1;
954 $hasPrivateCopyConstructor = 1 if ( $m->{Access
} eq 'private' );
957 # Hack the return type for constructors, since constructors return an object pointer
958 $m->{ReturnType
} = $className."*";
962 if ( $name =~ /~$classNode->{astNodeName}/ && $m->{Access
} ne "private" ) { # not used
963 $hasPublicDestructor = 0 if $m->{Access
} ne 'public';
964 #$hasVirtualDestructor = 1 if ( $m->{Flags} =~ "v" );
968 if ( $m->{Flags
} =~ "p" && $m->{Access
} =~ /private/ ) {
969 $hasPrivatePureVirtual = 1; # ouch, can't inherit from that one
972 # All we want from private methods is to check for virtuals, nothing else
973 next if ( $m->{Access
} =~ /private/ );
975 # Don't generate code for deprecated methods,
976 # or where the code won't compile/link for obscure reasons. Or even obvious reasons..
977 if ( $m->{Deprecated
}
978 # Assume only Qt classes have tr() and trUtf8() in their Q_OBJECT macro
979 || ($classNode->{astNodeName
} !~ /^Q/ and $name eq 'tr')
980 || ($classNode->{astNodeName
} !~ /^Q/ and $name eq 'trUtf8')
981 || $m->{ReturnType
} =~ /template/
982 || $m->{ReturnType
} =~ /QT3_SUPPORT/
983 || $name eq 'qt_metacast'
984 || $name eq 'virtual_hook'
986 || ($name eq 'qt_metacall')
987 || ($name eq 'metaObject')
988 || $name eq 'qWarning'
989 || $name eq 'qCritical'
991 || $name eq 'finalize'
992 || ($m->{ReturnType
} =~ /iterator/)
993 || ($classNode->{astNodeName
} eq 'QApplication' and $name eq 'QApplication')
994 || ($classNode->{astNodeName
} eq 'QCoreApplication' and $name eq 'QCoreApplication')
995 || ($classNode->{astNodeName
} eq 'QBoxLayout' and $name eq 'spacing')
996 || ($classNode->{astNodeName
} eq 'QBoxLayout' and $name eq 'setSpacing')
997 || ($classNode->{astNodeName
} eq 'QGraphicsWidget' and $name eq 'children')
998 || ($classNode->{astNodeName
} eq 'QGridLayout' and $name eq 'setSpacing')
999 || ($classNode->{astNodeName
} eq 'QGridLayout' and $name eq 'spacing')
1000 || ($classNode->{astNodeName
} eq 'QMessageBox' and $name eq 'setWindowTitle')
1001 || ($classNode->{astNodeName
} eq 'TextEvent' and $name eq 'data')
1002 || ($classNode->{astNodeName
} eq 'KCmdLineArgs' and $name eq 'init' and $m->{ParamList
}[0]->{ArgType
} =~ /int/)
1003 || ($classNode->{astNodeName
} eq 'KConfigGroup' and $name eq 'groupImpl')
1004 || ($classNode->{astNodeName
} eq 'KConfigGroup' and $name eq 'setReadDefaults')
1005 || ($classNode->{astNodeName
} eq 'KConfigGroup' and $name eq 'KConfigGroup' && $#{$m->{ParamList}} == 1 && $m->{ParamList}[0]->{ArgType} =~ /const KConfigBase/)
1006 || ($name eq 'operator<<' and $m->{ParamList
}[0]->{ArgType
} =~ /QDebug/ )
1007 || ($name eq 'operator<<' and $m->{ParamList
}[0]->{ArgType
} =~ /QDataStream/ and $m->{ParamList
}[1]->{ArgType
} =~ /KDateTime::Spec/ )
1008 || ($name eq 'operator>>' and $m->{ParamList
}[0]->{ArgType
} =~ /QDataStream/ and $m->{ParamList
}[1]->{ArgType
} =~ /KDateTime::Spec/ )
1009 || ($name eq 'operator<<' and $m->{ParamList
}[0]->{ArgType
} =~ /QDataStream/ and $m->{ParamList
}[1]->{ArgType
} =~ /const KDateTime/ )
1010 || ($name eq 'operator>>' and $m->{ParamList
}[0]->{ArgType
} =~ /QDataStream/ and $m->{ParamList
}[1]->{ArgType
} =~ /KDateTime/ )
1011 || ($classNode->{astNodeName
} eq 'KInputDialog' and $name eq 'getDouble')
1012 || ($classNode->{astNodeName
} eq 'KInputDialog' and $name eq 'getInteger')
1013 || ($classNode->{astNodeName
} eq 'KIO' and $name eq 'buildHTMLErrorString')
1014 || ($classNode->{astNodeName
} eq 'KJob' and $name eq 'description')
1015 || ($classNode->{astNodeName
} eq 'KJob' and $name eq 'KJob')
1016 || ($classNode->{astNodeName
} eq 'KShortcutsEditor' and $name eq 'checkGlobalShortcutsConflict')
1017 || ($classNode->{astNodeName
} eq 'KShortcutsEditor' and $name eq 'checkStandardShortcutsConflict')
1018 || ($classNode->{astNodeName
} eq 'KStandardShortcut' and $name eq 'insert')
1019 || ($classNode->{astNodeName
} eq 'KTzfileTimeZoneSource' and $name eq 'location')
1020 || ($classNode->{astNodeName
} eq 'Wallet' and $name eq 'Wallet')
1021 || ($classNode->{astNodeName
} eq 'KMD5' and $name eq 'transform') )
1023 $m->{NodeType
} = 'deleted';
1028 my $firstDefaultParam;
1029 foreach my $arg ( @
{$m->{ParamList
}} ) {
1030 # Look for first param with a default value
1031 if ( defined $arg->{DefaultValue
} && !defined $firstDefaultParam ) {
1032 $firstDefaultParam = $argId;
1035 if ( $arg->{ArgType
} eq '...' # refuse a method with variable arguments
1036 || $arg->{ArgType
} eq 'const QTextItem&' # ref to a private class
1037 || $arg->{ArgType
} eq 'DecoderFn' # QFile's callback
1038 || $arg->{ArgType
} eq 'EncoderFn' # QFile's callback
1039 || $arg->{ArgType
} eq 'FILE*' ) # won't be able to handle that I think
1041 $m->{NodeType
} = 'deleted';
1045 # Resolve type in full, e.g. for QSessionManager::RestartHint
1046 # (QSessionManagerJBridge doesn't inherit QSessionManager)
1047 $arg->{ArgType
} = kalyptusDataDict
::resolveType
($arg->{ArgType
}, $classNode, $rootnode);
1048 registerType
( $arg->{ArgType
} );
1052 $m->AddProp( "FirstDefaultParam", $firstDefaultParam );
1053 $m->{ReturnType
} = kalyptusDataDict
::resolveType
($m->{ReturnType
}, $classNode, $rootnode) if ($m->{ReturnType
});
1054 registerType
( $m->{ReturnType
} );
1056 elsif( $m->{NodeType
} eq "enum" ) {
1057 if ( ! $m->{astNodeName
} ) {
1058 $m->{Access
} = 'protected';
1060 my $fullEnumName = $className."::".$m->{astNodeName
};
1061 if ( ($fullEnumName eq 'KMimeType::Format' and $name eq 'compression')
1062 || $fullEnumName eq 'QDataStream::ByteOrder'
1063 || $m->{Deprecated
} ) {
1064 $m->{NodeType
} = 'deleted';
1068 $classNode->{enumerations
}{$m->{astNodeName
}} = $fullEnumName;
1069 # if $m->{astNodeName} and $m->{Access} ne 'private';
1070 # if $m->{astNodeName} ;
1072 # Define a type for this enum
1073 registerType
( $fullEnumName );
1075 # Remember that it's an enum
1076 findTypeEntry
( $fullEnumName )->{isEnum
} = 1;
1077 } elsif( $m->{NodeType
} eq 'property' ) {
1078 if ( ($classNode->{astNodeName
} eq 'QWidget' and $name eq 'Q_PROPERTY_height')
1079 || ($classNode->{astNodeName
} eq 'QWidget' and $name eq 'Q_PROPERTY_minimumSizeHint')
1080 || ($classNode->{astNodeName
} eq 'QWidget' and $name eq 'Q_PROPERTY_sizeHint')
1081 || ($classNode->{astNodeName
} eq 'QWidget' and $name eq 'Q_PROPERTY_visible')
1082 || ($classNode->{astNodeName
} eq 'QWidget' and $name eq 'Q_PROPERTY_width')
1083 || ($classNode->{astNodeName
} eq 'QStackedLayout' and $name eq 'Q_PROPERTY_count') )
1085 $m->{NodeType
} = 'deleted';
1088 # Don't generate C# code for the property's read and write methods
1090 if ( defined $m->{READ
} && $m->{READ
} ne '') {
1091 $method = kdocAstUtil
::findRef
( $classNode, $m->{READ
} );
1092 if ( defined $method
1093 && $#{$method->{ParamList}} == -1
1094 && $method->{Flags
} !~ 'v'
1095 && $method->{Access
} !~ /slots|signals/ )
1097 $method->{NodeType
} = 'deleted';
1101 if ( defined $m->{WRITE
} && $m->{WRITE
} ne '') {
1102 $method = kdocAstUtil
::findRef
( $classNode, $m->{WRITE
} );
1103 if ( defined $method
1104 && $#{$method->{ParamList}} == 0
1105 && $method->{Flags
} !~ 'v'
1106 && $method->{Access
} !~ /slots|signals/ )
1108 $method->{NodeType
} = 'deleted';
1111 } elsif( $m->{NodeType
} eq 'var' ) {
1112 if ($name eq 'staticMetaObject') {
1113 $m->{NodeType
} = 'deleted';
1116 my $varType = $m->{Type
};
1117 # We are interested in public static vars, like QColor::blue
1118 if ( $varType =~ s/static\s+// && $m->{Access
} ne 'private'
1119 && $className."::".$m->{astNodeName
} ne "KSpell::modalListText" )
1121 $varType =~ s/const\s+(.*)\s*&/$1/;
1122 $varType =~ s/\s*$//;
1123 print STDERR
"var: $m->{astNodeName} '$varType'\n" if ($debug);
1126 registerType
( $varType );
1129 # To avoid duplicating the above test, we just get rid of any other var
1130 $m->{NodeType
} = 'deleted';
1136 $main::doPrivate
= $doPrivate;
1138 print STDERR
"$className: ctor count: $constructorCount, hasPublicProtectedConstructor: $hasPublicProtectedConstructor, hasCopyConstructor: $hasCopyConstructor:, defaultConstructor: $defaultConstructor, hasPublicDestructor: $hasPublicDestructor, hasPrivatePureVirtual:$hasPrivatePureVirtual\n" if ($debug);
1140 # Note that if the class has _no_ constructor, the default ctor applies. Let's even generate it.
1141 if ( !$constructorCount && $defaultConstructor eq 'none' && !$hasPrivatePureVirtual ) {
1142 # Create a method node for the constructor
1143 my $methodNode = Ast
::New
( $classNode->{astNodeName
} );
1144 $methodNode->AddProp( "NodeType", "method" );
1145 $methodNode->AddProp( "Flags", "" );
1146 $methodNode->AddProp( "Params", "" );
1147 $methodNode->AddProp( "ParamList", [] );
1148 kdocAstUtil
::attachChild
( $classNode, $methodNode );
1150 # Hack the return type for constructors, since constructors return an object pointer
1151 $methodNode->AddProp( "ReturnType", $className."*" );
1152 registerType
( $className."*" );
1153 $methodNode->AddProp( "Access", "public" ); # after attachChild
1154 $defaultConstructor = 'public';
1155 $hasPublicProtectedConstructor = 1;
1158 # Also, if the class has no explicit destructor, generate a default one.
1159 if ( !$hasDestructor && !$hasPrivatePureVirtual ) {
1160 my $methodNode = Ast
::New
( "$classNode->{astNodeName}" );
1161 $methodNode->AddProp( "NodeType", "method" );
1162 $methodNode->AddProp( "Flags", "" );
1163 $methodNode->AddProp( "Params", "" );
1164 $methodNode->AddProp( "ParamList", [] );
1165 kdocAstUtil
::attachChild
( $classNode, $methodNode );
1167 $methodNode->AddProp( "ReturnType", "~" );
1168 $methodNode->AddProp( "Access", "public" );
1171 # If we have a private pure virtual, then the class can't be instanciated (e.g. QCanvasItem)
1172 # Same if the class has only private constructors (e.g. QInputDialog)
1173 $classNode->AddProp( "CanBeInstanciated", $hasPublicProtectedConstructor
1174 # && !$hasPrivatePureVirtual
1175 && (!$classNode->{Pure
} or $classNode->{astNodeName
} eq 'QValidator')
1176 && !($classNode->{NodeType
} eq 'namespace')
1177 && ($classNode->{astNodeName
} !~ /^DrawContentsEvent$|^MouseEvent$|^MouseDoubleClickEvent$|^MouseMoveEvent$|^MouseReleaseEvent$|^MousePressEvent$/)
1178 && ($classNode->{astNodeName
} !~ /QMetaObject|QDragObject|Slave|CopyJob|KMdiChildFrm|KNamedCommand/) );
1180 # We will derive from the class only if it has public or protected constructors.
1181 # (_Even_ if it has pure virtuals. But in that case the *.cpp class can't be instantiated either.)
1182 $classNode->AddProp( "BindingDerives", $hasPublicProtectedConstructor );
1184 # We need a public dtor to destroy the object --- ### aren't protected dtors ok too ??
1185 $classNode->AddProp( "HasPublicDestructor", $hasPublicDestructor );
1187 # Hack for QAsyncIO. We don't implement the "if a class has no explicit copy ctor,
1188 # then all of its member variables must be copiable, otherwise the class isn't copiable".
1189 $hasPrivateCopyConstructor = 1 if ( $className eq 'QAsyncIO' );
1191 # Remember if this class can't be copied - it means all its descendants can't either
1192 $classNode->AddProp( "CanBeCopied", !$hasPrivateCopyConstructor );
1193 $classNode->AddProp( "HasCopyConstructor", $hasCopyConstructor );
1194 if ($classNode->{astNodeName
} =~ /Abstract/
1195 || $classNode->{astNodeName
} eq 'QAccessibleInterface'
1196 || $classNode->{astNodeName
} eq 'QAccessibleApplication'
1197 || $classNode->{astNodeName
} eq 'QAccessibleObjectEx'
1198 || $classNode->{astNodeName
} eq 'QAccessibleWidgetEx'
1199 || $classNode->{astNodeName
} eq 'QAccessibleObject' )
1201 $classNode->AddProp( "Pure", 1 );
1205 sub propagateCanBeCopied
($)
1207 my $classNode = shift;
1208 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
1209 my @super = superclass_list
($classNode);
1210 # A class can only be copied if none of its ancestors have a private copy ctor.
1211 for my $s (@super) {
1212 if (!$s->{CanBeCopied
}) {
1213 $classNode->{CanBeCopied
} = 0;
1214 print STDERR
"$classNode->{astNodeName} cannot be copied\n" if ($debug);
1219 # Prepare the {case} dict for the class
1220 prepareCaseDict
( $classNode );
1223 sub generateClass
($$$$$)
1225 my( $node, $packagename, $namespace, $indent, $addImport ) = @_;
1226 my $className = join( "::", kdocAstUtil
::heritage
($node) );
1227 my $csharpClassName = $node->{astNodeName
};
1229 my %csharpMethods = ();
1230 # my %addImport = ();
1233 my @ancestor_nodes = ();
1234 Iter
::Ancestors
( $node, $rootnode, undef, undef, sub {
1235 my ( $ances, $name, $type, $template ) = @_;
1236 if ( $name ne "khtml::KHTMLWidget"
1237 and $name !~ /QList</ and $name ne 'QList' and $name !~ /QVector/
1238 and $name !~ /QMap/ and $name !~ /QHash/
1239 and $name ne 'KShared' and $name ne 'QSharedData' and $name ne '' ) {
1240 if (defined $ances) {
1241 push @ancestor_nodes, $ances;
1242 my $ancestorName = join( ".", kdocAstUtil
::heritage
($ances) );
1243 push @ancestors, $ancestorName;
1250 my ($methodCode, $staticMethodCode, $interfaceCode, $proxyInterfaceCode, $signalCode, $extraCode, $enumCode, $notConverted) = generateAllMethods
( $node, $#ancestors + 1,
1256 my $tempMethodNumber = $methodNumber;
1258 # Add method calls for the interfaces implemented by the class
1259 foreach my $ancestor_node ( @ancestor_nodes ) {
1260 if ( defined $interfacemap{$ancestor_node->{astNodeName
}} && ($#ancestors > 0) ) {
1261 my ($meth, $static, $interf, $proxyInterf, $sig, $extra, $enum, $notconv) = generateAllMethods
( $ancestor_node, 0, \
%csharpMethods, $node, 0, $addImport );
1262 $methodCode .= $meth;
1263 $staticMethodCode .= $static;
1264 $extraCode .= $extra;
1266 $interfaceCode .= $interf;
1267 $proxyInterfaceCode .= $proxyInterf;
1268 $notConverted .= $notconv;
1272 my $globalSpace = kdocAstUtil
::findRef
( $rootnode, $main::globalSpaceClassName
);
1273 my ($meth, $static, $interf, $proxyInterf, $sig, $extra, $enum, $notconv) = generateAllMethods
( $globalSpace, 0, \
%csharpMethods, $node, 0, $addImport );
1274 $methodCode .= $meth;
1275 $staticMethodCode .= $static;
1276 $extraCode .= $extra;
1278 $interfaceCode .= $interf;
1279 $proxyInterfaceCode .= $proxyInterf;
1280 $notConverted .= $notconv;
1281 $methodNumber = $tempMethodNumber;
1283 if ( $className eq 'Qt' ) {
1286 if ( $className eq 'QListViewItem'
1287 || $className eq 'QAbstractTextDocumentLayout'
1288 || $className eq 'QUriDrag'
1289 || $className eq 'KDE' ) {
1290 # Special case these two classes as they have methods that use ArrayList added as 'extras'
1291 $classCode .= "$indent\tusing System.Collections.Generic;\n";
1294 if ( $className eq 'QObject' ) {
1295 $classCode .= "$indent\tusing System.Reflection;\n";
1299 if ( $enumCode ne '' ) {
1300 $classCode .= "$enumCode" if ($node->{NodeType
} eq 'namespace'
1301 && $csharpClassName ne 'Qt'
1302 && $csharpClassName ne 'KDE');
1305 if ( defined $interfacemap{$csharpClassName} ) {
1306 $classCode .= "\n$indent\tpublic interface " . $interfacemap{$csharpClassName} . " {\n";
1307 $classCode .= $interfaceCode;
1308 $classCode .= "$indent\t}\n";
1312 my $parentClassName = "";
1314 if ($node->{NodeType
} eq 'namespace') {
1315 $classdec .= "\t[SmokeClass(\"$className\")]\n";
1316 # $classdec .= "\tnamespace $className {\n";
1318 $csharpClassName = 'Global' unless ($csharpClassName eq 'Qt' || $csharpClassName eq 'KDE');
1320 if ( $partial_classes{$csharpClassName} ) {
1321 $classdec .= "\tpublic partial class $csharpClassName {\n";
1323 $classdec .= "\tpublic class $csharpClassName {\n";
1326 if ( $csharpClassName eq 'Qt' ) {
1327 $classdec .= "\t\tprotected SmokeInvocation interceptor = null;\n";
1329 } elsif ( $#ancestors < 0 ) {
1330 $classdec .= "\t[SmokeClass(\"$className\")]\n";
1332 if ( $csharpClassName eq 'QObject' ) {
1333 $classdec .= "\tpublic partial class QObject : Qt, IDisposable {\n";
1334 $classdec .= "\t\tprivate IntPtr smokeObject;\n";
1335 $classdec .= "\t\tprotected Object Q_EMIT = null;\n";
1336 $classdec .= "\t\tprotected $csharpClassName(Type dummy) {\n";
1337 $classdec .= "\t\t\ttry {\n";
1338 $classdec .= "\t\t\t\tType proxyInterface = Qyoto.GetSignalsInterface(GetType());\n";
1339 $classdec .= "\t\t\t\tSignalInvocation realProxy = new SignalInvocation(proxyInterface, this);\n";
1340 $classdec .= "\t\t\t\tQ_EMIT = realProxy.GetTransparentProxy();\n";
1341 $classdec .= "\t\t\t}\n";
1342 $classdec .= "\t\t\tcatch {\n";
1343 $classdec .= "\t\t\t\tConsole.WriteLine(\"Could not retrieve signal interface\");\n";
1344 $classdec .= "\t\t\t}\n";
1345 $classdec .= "\t\t}\n";
1346 $classdec .= "\t\t[SmokeMethod(\"metaObject()\")]\n";
1347 $classdec .= "\t\tpublic virtual QMetaObject MetaObject() {\n";
1348 $classdec .= "\t\t\tif (SmokeMarshallers.IsSmokeClass(GetType())) {\n";
1349 $classdec .= "\t\t\t\treturn (QMetaObject) interceptor.Invoke(\"metaObject\", \"metaObject()\", typeof(QMetaObject));\n";
1350 $classdec .= "\t\t\t} else {\n";
1351 $classdec .= "\t\t\t\treturn Qyoto.GetMetaObject(this);\n";
1352 $classdec .= "\t\t\t}\n";
1353 $classdec .= "\t\t}\n";
1355 if ( $node->{Pure
} ) {
1356 $classdec .= "\tpublic abstract ";
1358 $classdec .= "\tpublic ";
1361 if ( $partial_classes{$csharpClassName} ) {
1362 $classdec .= "partial class $csharpClassName : Object";
1364 $classdec .= "class $csharpClassName : Object";
1366 if ( defined $interfacemap{$csharpClassName} ) {
1367 $classdec .= ", " . $interfacemap{$csharpClassName};
1370 if ($node->{CanBeInstanciated
} and $node->{HasPublicDestructor
} and !$node->{Pure
}) {
1371 $classdec .= ", IDisposable";
1374 if (defined $iterator_interfacemap{$className}) {
1375 $classdec .= ", $iterator_interfacemap{$className}";
1378 $classdec .= " {\n\t\tprotected SmokeInvocation interceptor = null;\n";
1379 $classdec .= "\t\tprivate IntPtr smokeObject;\n";
1380 $classdec .= "\t\tprotected $csharpClassName(Type dummy) {}\n";
1383 $classdec .= "\t[SmokeClass(\"$className\")]\n";
1384 if ( $partial_classes{$csharpClassName} ) {
1386 || $csharpClassName eq 'QAccessibleInterface'
1387 || $csharpClassName eq 'QAccessibleApplication'
1388 || $csharpClassName eq 'QAccessibleObjectEx'
1389 || $csharpClassName eq 'QAccessibleWidgetEx'
1390 || $csharpClassName eq 'QAccessibleObject' )
1392 $classdec .= "\tpublic abstract partial class $csharpClassName : ";
1394 $classdec .= "\tpublic partial class $csharpClassName : ";
1397 if ( $node->{Pure
} ) {
1398 $classdec .= "\tpublic abstract class $csharpClassName : ";
1400 $classdec .= "\tpublic class $csharpClassName : ";
1404 foreach $ancestor ( @ancestors ) {
1405 if ( !defined $interfacemap{$ancestor} or $ancestor eq @ancestors[$#ancestors] ) {
1406 $parentClassName .= "$ancestor";
1407 $classdec .= "$ancestor";
1412 my @implements = ();
1413 if ( $#ancestors >= 1 ) {
1414 foreach $ancestor ( @ancestors ) {
1415 if ( defined $interfacemap{$ancestor} ) {
1416 push(@implements, $interfacemap{$ancestor});
1421 if ($#implements >= 0) {
1423 $classdec .= join(", ", @implements);
1426 if ($node->{CanBeInstanciated
} and $node->{HasPublicDestructor
} and !$node->{Pure
}) {
1427 $classdec .= ", IDisposable";
1430 if (defined $iterator_interfacemap{$className}) {
1431 $classdec .= ", $iterator_interfacemap{$className}";
1434 $classdec .= " {\n";
1435 $classdec .= " \t\tprotected $csharpClassName(Type dummy) : base((Type) null) {}\n";
1438 if ( $csharpClassName !~ /^Q/ or $signalCode ne '' ) {
1439 my $signalLink = '';
1440 if ( $signalCode ne '' ) {
1441 $signalLink = " See <see cref=\"I$csharpClassName" . "Signals\"></see> for signals emitted by $csharpClassName\n";
1443 my $docnode = $node->{DocNode
};
1444 if ( defined $docnode ) {
1445 my $comment = printCSharpdocComment
( $docnode, "", "$indent\t/// ", $signalLink );
1446 $classCode .= $comment;
1448 $classCode .= "$indent\t///$signalLink";
1452 $classCode .= indentText
($indent, $classdec);
1454 # only generate nested classes
1455 if ($node->{NodeType
} ne 'namespace') {
1456 Iter
::MembersByType
( $node, undef,
1457 sub { my ($node, $subclassNode ) = @_;
1458 if ( $subclassNode->{NodeType
} =~ /class|struct/ && !defined $subclassNode->{Compound
} ) {
1459 $classCode .= generateClass
($subclassNode, $packagename, $namespace, $indent . "\t", $addImport);
1463 Iter
::MembersByType
( $node, undef,
1464 sub { my ($node, $subclassNode ) = @_;
1465 if ( $subclassNode->{NodeType
} =~ /class|struct/ && $subclassNode->{Compound
} ) {
1466 $classCode .= generateClass
($subclassNode, $packagename, $namespace, $indent . "\t", $addImport);
1471 if ($methodCode ne '') {
1472 if ( $#ancestors < 0 ) {
1473 $classCode .= "$indent\t\tprotected void CreateProxy() {\n";
1475 $classCode .= "$indent\t\tprotected new void CreateProxy() {\n";
1477 $classCode .= "$indent\t\t\tinterceptor = new $main::smokeInvocation(typeof($csharpClassName), this);\n$indent\t\t}\n";
1480 if ($proxyInterfaceCode ne '') {
1481 $classCode .= "$indent\t\tprivate static SmokeInvocation staticInterceptor = null;\n";
1482 $classCode .= "$indent\t\tstatic $csharpClassName() {\n";
1483 $classCode .= "$indent\t\t\tstaticInterceptor = new $main::smokeInvocation(typeof($csharpClassName), null);\n";
1484 $classCode .= "$indent\t\t}\n";
1487 if ( $enumCode ne '' ) {
1488 $classCode .= indentText
("$indent\t", "$enumCode") unless ($node->{NodeType
} eq 'namespace'
1489 && $csharpClassName ne 'Qt'
1490 && $csharpClassName ne 'KDE');
1492 $classCode .= indentText
($indent, $extraCode);
1493 $classCode .= indentText
($indent, $notConverted);
1494 $classCode .= indentText
($indent, $methodCode);
1495 $classCode .= indentText
($indent, $staticMethodCode);
1497 if ( is_kindof
($node, "QObject") ) {
1498 if ( $csharpClassName eq 'QObject' ) {
1499 $classCode .= "$indent\t\tprotected I" . $csharpClassName . "Signals Emit {\n";
1501 $classCode .= "$indent\t\tprotected new I" . $csharpClassName . "Signals Emit {\n";
1504 $classCode .= "$indent\t\t\tget { return (I" . $csharpClassName . "Signals) Q_EMIT; }\n";
1505 $classCode .= "$indent\t\t}\n";
1506 $classCode .= "$indent\t}\n";
1508 $classCode .= "\n$indent\tpublic interface I$csharpClassName" . "Signals";
1509 if ($parentClassName =~ /(.*)[.](.*)/) {
1510 $classCode .= " : $1.I" . $2 . "Signals" unless $csharpClassName eq "QObject";
1512 $classCode .= " : I" . $parentClassName . "Signals" unless $csharpClassName eq "QObject";
1514 $classCode .= " {\n";
1515 $classCode .= $signalCode;
1516 $classCode .= "$indent\t}\n";
1518 $classCode .= "$indent\t}\n";
1524 =head2 writeClassDoc
1526 Called by writeDoc for each class to be written out
1534 my $className = join( "::", kdocAstUtil
::heritage
($node) );
1535 my $csharpClassName = $node->{astNodeName
};
1536 # Makefile doesn't like '::' in filenames, so use __
1537 my $fileName = $className;
1538 $fileName =~ s/::/_/g;
1539 # my $fileName = join( "__", kdocAstUtil::heritage($node) );
1540 print "Enter: $className\n" if $debug;
1543 if ($className =~ /^Qsci/) {
1544 $packagename = "QScintilla";
1545 } elsif ($className =~ /^Qwt/) {
1546 $packagename = "Qwt";
1547 } elsif ($className =~ /^Q/) {
1548 $packagename = "Qyoto";
1549 } elsif ($className =~ /^Plasma/) {
1550 $packagename = "Plasma";
1551 } elsif ($className =~ /^Soprano/) {
1552 $packagename = "Soprano";
1554 $packagename = "Kimono";
1557 my $namespace, my @parentClasses;
1560 foreach my $n (kdocAstUtil
::refHeritage
($node)) {
1561 if ($n->{NodeType
} eq 'namespace') {
1562 $namespace .= "." if !$first;
1563 $namespace .= "$n->{astNodeName}"
1565 push @parentClasses, $n->{astNodeName
} if $n != $node;
1570 # nested classes go into the same source file as the containing class
1571 return if (scalar(@parentClasses) > 0);
1575 # Write out the *.csharp file
1576 my $classFile = "$outputdir/$fileName.cs";
1577 open( CLASS
, ">$classFile" ) || die "Couldn't create $classFile\n";
1578 print STDERR
"Writing $fileName.csharp\n" if ($debug);
1580 print CLASS
"//Auto-generated by kalyptus. DO NOT EDIT.\n";
1581 # print CLASS "//Auto-generated by $0. DO NOT EDIT.\n";
1583 $namespace = undef if ($namespace eq 'KDE' or $namespace eq 'Qt');
1584 # only the core classes go into the Kimono namespace, others have there own one.
1585 if (defined $namespace) {
1586 print CLASS
"namespace $namespace {\n";
1587 print CLASS
"\tusing $packagename;\n";
1589 print CLASS
"namespace $packagename {\n";
1592 print CLASS
"\tusing System;\n";
1594 my $classCode = generateClass
($node, $packagename, $namespace, "", \
%addImport);
1596 foreach my $imp (keys %addImport) {
1598 # Ignore any imports for classes in the same package as the current class
1599 if ($imp !~ /$packagename/) {
1600 print CLASS
"\tusing $imp;\n";
1604 print CLASS
$classCode;
1612 # Generate the prototypes for a method (one per arg with a default value)
1613 # Helper for makeprotos
1614 sub iterproto
($$$$$) {
1615 my $classidx = shift; # to check if a class exists
1619 my $protolist = shift;
1621 my $argcnt = scalar @
{ $method->{ParamList
} } - 1;
1622 if($idx > $argcnt) {
1623 push @
$protolist, $proto;
1626 if(defined $method->{FirstDefaultParam
} and $method->{FirstDefaultParam
} <= $idx) {
1627 push @
$protolist, $proto;
1630 my $arg = $method->{ParamList
}[$idx]->{ArgType
};
1632 my $typeEntry = findTypeEntry
( $arg );
1633 my $realType = $typeEntry->{realType
};
1636 $arg =~ s/\bconst\b//g;
1638 if($typeEntry->{isEnum
} || $allTypes{$realType}{isEnum
} || exists $typeunion{$realType} || exists $mungedTypeMap{$arg})
1640 my $id = '$'; # a 'scalar
1641 $id = '?' if $arg =~ /[*&]{2}/;
1642 $id = $mungedTypeMap{$arg} if exists $mungedTypeMap{$arg};
1643 iterproto
($classidx, $method, $proto . $id, $idx + 1, $protolist);
1648 if(exists $classidx->{$realType}) {
1649 iterproto
($classidx, $method, $proto . '#', $idx + 1, $protolist);
1653 # A non-scalar (reference to array or hash, undef)
1654 iterproto
($classidx, $method, $proto . '?', $idx + 1, $protolist);
1658 # Generate the prototypes for a method (one per arg with a default value)
1659 sub makeprotos
($$$) {
1660 my $classidx = shift;
1662 my $protolist = shift;
1663 iterproto
($classidx, $method, $method->{astNodeName
}, 0, $protolist);
1666 # Return the string containing the signature for this method (without return type).
1667 # If the 2nd arg is not the size of $m->{ParamList}, this method returns a
1668 # partial signature (this is used to handle default values).
1669 sub argsSignature
($$) {
1672 # my $sig = $method->{astNodeName};
1676 foreach my $arg ( @
{$method->{ParamList
}} ) {
1677 last if $argId > $last;
1678 push @argTypeList, $arg->{ArgType
};
1681 $sig .= "(". join(", ",@argTypeList) .")";
1682 $sig .= " const" if $method->{Flags
} =~ "c";
1686 # Return the string containing the signature for this method (without return type).
1687 # If the 2nd arg is not the size of $m->{ParamList}, this method returns a
1688 # partial signature (this is used to handle default values).
1689 sub methodSignature
($$) {
1692 my $sig = $method->{astNodeName
};
1695 foreach my $arg ( @
{$method->{ParamList
}} ) {
1696 last if $argId > $last;
1697 push @argTypeList, $arg->{ArgType
};
1700 $sig .= "(". join(", ",@argTypeList) .")";
1701 $sig .= " const" if $method->{Flags
} =~ "c";
1705 # Return the string containing the signature for this method (without return type).
1706 # If the 2nd arg is not the size of $m->{ParamList}, this method returns a
1707 # partial signature (this is used to handle default values).
1708 sub mungedSignature
($$) {
1711 # my $sig = $method->{astNodeName};
1714 foreach my $arg ( @
{$method->{ParamList
}} ) {
1715 last if $argId > $last;
1716 $sig .= mungedArgType
($method, $arg->{ArgType
});
1722 # Return the string containing the csharp signature for this method (without return type).
1723 # If the 2nd arg is not the size of $m->{ParamList}, this method returns a
1724 # partial signature (this is used to handle default values).
1725 sub csharpMethodSignature
($$) {
1728 my $sig = $method->{astNodeName
};
1731 foreach my $arg ( @
{$method->{ParamList
}} ) {
1733 last if $argId > $last;
1734 push @argTypeList, cplusplusToCSharp
( $arg->{ArgType
} );
1736 $sig .= "(". join(", ",@argTypeList) .")";
1740 sub smokeInvocation
($$$$$$) {
1741 my ( $target, $argtypes, $returnType, $mungedMethod, $signature, $addImport ) = @_;
1743 my $methodCode = "\t\t\t";
1744 if ($returnType ne 'void') {
1745 $methodCode .= "return ($returnType) ";
1748 $methodCode .= "$target.Invoke(\"$mungedMethod\", \"$signature\", typeof($returnType)";
1751 foreach my $arg ( @
{$argtypes} ) {
1752 $arg =~ /^(ref )?(.*)\s(.*)$/;
1754 return smokeRefInvocation
($target, $argtypes, $returnType, $mungedMethod, $signature, $addImport);
1756 $arglist .= ", typeof($2), $3";
1759 return $methodCode . $arglist . ");\n";
1762 sub smokeRefInvocation
($$$$$$) {
1763 my ( $target, $argtypes, $returnType, $mungedMethod, $signature, $addImport ) = @_;
1765 my $preMethodCode = "";
1766 my $methodCode = "";
1767 my $postMethodCode = "";
1769 $preMethodCode = "\t\t\tStackItem[] stack = new StackItem[" . (scalar(@
{$argtypes}) + 1) . "];\n";
1770 $methodCode .= "\t\t\t$target.Invoke(\"$mungedMethod\", \"$signature\", stack);\n";
1774 foreach my $arg ( @
{$argtypes} ) {
1775 $arg =~ /^(ref )?(.*)\s(.*)$/;
1780 $preMethodCode .= "\t\t\tstack[$argNo].s_$argtype = $argname;\n";
1781 $postMethodCode .= "\t\t\t$argname = stack[$argNo].s_$argtype;\n";
1782 } elsif ($argtype =~ /^int$|^uint$|^bool$|^double$|^float$|^long$|^ulong$|^short$|^ushort$/ ) {
1783 $preMethodCode .= "\t\t\tstack[$argNo].s_$argtype = $argname;\n";
1784 } elsif ($argtype =~ /\./ ) {
1785 $preMethodCode .= "\t\t\tstack[$argNo].s_int = (int) $argname;\n";
1787 $addImport->{"System.Runtime.InteropServices"} = 1;
1788 $preMethodCode .= "#if DEBUG\n";
1789 $preMethodCode .= "\t\t\tstack[$argNo].s_class = (IntPtr) DebugGCHandle.Alloc($argname);\n";
1790 $preMethodCode .= "#else\n";
1791 $preMethodCode .= "\t\t\tstack[$argNo].s_class = (IntPtr) GCHandle.Alloc($argname);\n";
1792 $preMethodCode .= "#endif\n";
1794 $postMethodCode .= "#if DEBUG\n";
1795 $postMethodCode .= "\t\t\tDebugGCHandle.Free((GCHandle) stack[$argNo].s_class);\n";
1796 $postMethodCode .= "#else\n";
1797 $postMethodCode .= "\t\t\t((GCHandle) stack[$argNo].s_class).Free();\n";
1798 $postMethodCode .= "#endif\n";
1802 # $arglist .= ", typeof($2), $3";
1805 if ($returnType eq 'void' ) {
1806 $postMethodCode .= "\t\t\treturn;\n";
1807 } elsif ($returnType =~ /^int$|^uint$|^bool$|^double$|^float$|^long$|^ulong$|^short$|^ushort$/ ) {
1808 $postMethodCode .= "\t\t\treturn stack[0].s_$returnType;\n";
1809 } elsif ($returnType =~ /\./ ) {
1810 $postMethodCode .= "\t\t\treturn ($returnType) Enum.ToObject(typeof($returnType), stack[0].s_int);\n";
1812 $addImport->{"System.Runtime.InteropServices"} = 1;
1813 $postMethodCode .= "\t\t\tobject returnValue = ((GCHandle) stack[0].s_class).Target;\n";
1815 $postMethodCode .= "#if DEBUG\n";
1816 $postMethodCode .= "\t\t\tDebugGCHandle.Free((GCHandle) stack[0].s_class);\n";
1817 $postMethodCode .= "#else\n";
1818 $postMethodCode .= "\t\t\t((GCHandle) stack[0].s_class).Free();\n";
1819 $postMethodCode .= "#endif\n";
1821 $postMethodCode .= "\t\t\treturn ($returnType) returnValue;\n";
1824 return $preMethodCode . $methodCode . $postMethodCode;
1827 sub smokeInvocationArgList
($) {
1828 my $argtypes = shift;
1831 foreach my $arg ( @
{$argtypes} ) {
1832 if ( $arg =~ /^(ref )?(.*)\s(.*)$/ ) {
1833 $arglist .= ", typeof($2), $3";
1839 sub coerce_type
($$$$) {
1844 my $new = shift; # 1 if this is a return value, 0 for a normal param
1846 my $typeEntry = findTypeEntry
( $type );
1847 my $realType = $typeEntry->{realType
};
1849 my $unionfield = $typeEntry->{typeId
};
1850 # die "$type" unless defined( $unionfield );
1851 if ( ! defined( $unionfield ) ) {
1852 print STDERR
"type field not defined: $type\n";
1856 $unionfield =~ s/t_/s_/;
1858 $type =~ s/\s+const$//; # for 'char* const'
1859 $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'
1861 my $code = "$union.$unionfield = ";
1863 $code .= "(void*)&$var;\n";
1864 } elsif($type =~ /\*$/) {
1865 $code .= "(void*)$var;\n";
1867 if ( $unionfield eq 's_class'
1868 or ( $unionfield eq 's_voidp' and $type ne 'void*' )
1869 or $type eq 'QString' ) { # hack
1870 $type =~ s/^const\s+//;
1872 $code .= "(void*)new $type($var);\n";
1874 $code .= "(void*)&$var;\n";
1884 # Generate the list of args casted to their real type, e.g.
1885 # (QObject*)x[1].s_class,(QEvent*)x[2].s_class,x[3].s_int
1886 sub makeCastedArgList
1889 my $i = 1; # The args start at x[1]. x[0] is the return value
1895 my $typeEntry = findTypeEntry
( $type );
1896 my $unionfield = $typeEntry->{typeId
};
1897 # die "$type" unless defined( $unionfield );
1898 if ( ! defined( $unionfield ) ) {
1899 print STDERR
"type field not defined: $type\n";
1902 $unionfield =~ s/t_/s_/;
1904 $type =~ s/\s+const$//; # for 'char* const'
1905 $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'
1909 $cast = "*($type *)";
1910 } elsif($type =~ /\*$/) {
1912 } elsif($type =~ /\(\*\)\s*\(/) { # function pointer ... (*)(...)
1915 if ( $unionfield eq 's_class'
1916 or ( $unionfield eq 's_voidp' and $type ne 'void*' )
1917 or $type eq 'QString' ) { # hack
1918 $cast = "*($type *)";
1923 push @castedList, "$type$v";
1930 # Adds the import for node $1 to be imported in $2 if not already there
1931 # Prints out debug stuff if $3
1932 sub addImportForClass
($$$)
1934 my ( $node, $addImport, $debugMe ) = @_;
1935 my $importname = csharpImport
( $node->{astNodeName
} );
1936 # print " Importing $importname for node name: " . $node->{astNodeName} . "\n";
1937 # No import needed, so return
1938 return if ( $importname eq '' );
1939 unless ( defined $addImport->{$importname} ) {
1940 print " Importing $importname\n" if ($debugMe);
1941 $addImport->{$importname} = 1;
1943 else { print " $importname already imported.\n" if ($debugMe); }
1946 sub checkImportsForObject
($$$)
1949 my $addImport = shift;
1955 $type = kalyptusDataDict
::resolveType
($type, $classNode, $rootnode);
1956 my $csharptype = cplusplusToCSharp
($type);
1957 if ( $csharptype eq 'ArrayList' ) {
1958 $addImport->{"System.Collections"} = 1;
1959 } elsif ( $csharptype =~ /^List</ ) {
1960 $addImport->{"System.Collections.Generic"} = 1;
1961 } elsif ( $csharptype =~ /^Dictionary</ ) {
1962 $addImport->{"System.Collections.Generic"} = 1;
1963 } elsif ( $csharptype =~ /StringBuilder/ ) {
1964 $addImport->{"System.Text"} = 1;
1968 sub mungedArgType
($$) {
1972 # my $arg = $method->{ParamList}[$idx]->{ArgType};
1974 my $typeEntry = findTypeEntry
( $arg );
1975 my $realType = $typeEntry->{realType
};
1978 $arg =~ s/\bconst\b//g;
1980 #print($method->{astNodeName} . " realType: " . $realType . " arg: $arg\n");
1982 if($typeEntry->{isEnum
} || $allTypes{$realType}{isEnum
} || exists $typeunion{$realType} || exists $mungedTypeMap{$arg})
1984 my $id = '$'; # a 'scalar
1985 $id = '?' if $arg =~ /[*&]{2}/;
1986 $id = $mungedTypeMap{$arg} if exists $mungedTypeMap{$arg};
1991 if(exists $new_classidx{$realType}) {
1995 # A non-scalar (reference to array or hash, undef)
1999 sub generateMethod
($$$$$$$$$)
2001 my( $virtualMethods, $overridenMethods, $classNode, $m, $addImport, $ancestorCount, $csharpMethods, $mainClassNode, $generateConstructors ) = @_; # input
2002 my $methodCode = ''; # output
2003 my $staticMethodCode = ''; # output
2004 my $interfaceCode = ''; # output
2005 my $proxyInterfaceCode = ''; # output
2006 my $signalCode = ''; # output
2007 my $notConverted = ''; # output
2009 my $name = $m->{astNodeName
}; # method name
2011 my @heritage = kdocAstUtil
::heritage
($classNode);
2012 my $className = join( "::", @heritage );
2014 @heritage = kdocAstUtil
::heritage
($mainClassNode);
2015 my $mainClassName = join( "::", @heritage );
2017 # The csharpClassName might be 'QWidget', while currentClassName is 'QRangeControl'
2018 # and the QRangeControl methods are being copied into QWidget.
2019 my $csharpClassName = $mainClassNode->{astNodeName
};
2020 my $currentClassName = $classNode->{astNodeName
};
2022 my $firstUnknownArgType = 99;
2023 my $returnType = $m->{ReturnType
};
2025 # Don't use $className here, it's never the fully qualified (A::B) name for a ctor.
2026 my $isConstructor = ($name eq $classNode->{astNodeName
} );
2027 my $isDestructor = ($returnType eq '~');
2029 my $isStatic = $m->{Flags
} =~ "s" || $classNode->{NodeType
} eq 'namespace';
2030 my $isPure = $m->{Flags
} =~ "p";
2031 my $fullSignature = methodSignature
( $m, $#{$m->{ParamList}} );
2033 # Don't generate anything for destructors, or constructors for namespaces
2034 return if $isDestructor
2035 or ($classNode->{NodeType
} eq 'namespace' and $isConstructor)
2036 # or (!$mainClassNode->{CanBeInstanciated} and $m->{Access} =~ /protected/)
2037 or $name =~ /^operator\s*(=|(\[\])|([|&^+-]=)|(!=))\s*$/
2038 or (!$isStatic and $name =~ /^operator\s*((\+\+)|(--))$/ and $#{$m->{ParamList}} == 0)
2039 or ($name =~ /^operator\s*\*$/ and $#{$m->{ParamList}} == -1);
2041 my $item = kdocAstUtil
::findRef
( $classNode, "Q_PROPERTY_" . $name );
2043 && $item->{NodeType
} eq 'property'
2045 && $#{$m->{ParamList}} == -1
2046 && $m->{Flags
} !~ 'v'
2047 && $m->{Access
} !~ /slots|signals/) {
2048 # If there is a property with the same name, don't bother
2051 my $propertyName = $name;
2052 if ( @
{$m->{ParamList
}} == 1 && $propertyName =~ /^set(.)(.*)/ ) {
2053 $propertyName = "Q_PROPERTY_" . lc($1) . $2;
2054 $item = kdocAstUtil
::findRef
( $classNode, $propertyName );
2056 && $item->{NodeType
} eq 'property'
2058 && $m->{Flags
} !~ 'v'
2059 && $m->{Access
} !~ /slots|signals/ )
2061 # If there is a property with the same name, don't bother
2066 if ($classNode->{astNodeName
} eq $main::globalSpaceClassName
) {
2067 my $sourcename = $m->{Source
}->{astNodeName
};
2068 # Only put Global methods which came from sources beginning with q into class Qt
2069 if ($csharpClassName eq 'Qt' and ( $sourcename !~ /\/q
[^\
/]*$/ or $sourcename =~ /string.h$/ or $sourcename =~ /qwt/ )) {
2072 # ..and any other global methods into KDE
2073 if ($csharpClassName eq 'KDE' and $m->{Source
}->{astNodeName
} =~ /\/q
[^\
/]*$/) {
2077 if ( $sourcename !~ s!.*(kio/|kparts/|dom/|kabc/|ksettings/|kjs/|ktexteditor/|kdeprint/|kdesu/)(.*)!$1$2!m ) {
2078 $sourcename =~ s!.*/(.*)!$1!m;
2080 if ( $sourcename eq '' ) {
2085 if ($returnType eq 'void') {
2086 $returnType = undef;
2088 # Detect objects returned by value
2089 checkImportsForObject
( $returnType, $addImport, $classNode );
2092 my $hasDuplicateSignature = 0;
2094 return if ( $m->{SkipFromSwitch
} && $m->{Flags
} !~ "p" );
2099 my @csharpArgTypeList=();
2100 my @csharpArgTypeOnlyList = ();
2102 foreach my $arg ( @
{$m->{ParamList
}} ) {
2105 if ( $arg->{ArgName
} =~ /^ref$|^super$|^int$|^params$|^env$|^cls$|^obj$|^byte$|^event$|^base$|^object$|^in$|^out$|^checked$|^delegate$|^string$|^interface$|^override$|^lock$/ ) {
2106 $arg->{ArgName
} = "";
2109 if ( $arg->{ArgName
} =~ /^short$|^long$/ ) {
2110 # Oops looks like a parser error
2111 $arg->{ArgType
} = $arg->{ArgName
};
2112 $arg->{ArgName
} = "";
2115 print STDERR
" Param ".$arg->{astNodeName
}." type: ".$arg->{ArgType
}." name:".$arg->{ArgName
}." default: ".$arg->{DefaultValue
}." csharp: ".cplusplusToCSharp
($arg->{ArgType
})."\n" if ($debug);
2117 my $argType = $arg->{ArgType
};
2122 if ( cplusplusToCSharp
($argType) eq "" && $firstUnknownArgType > $argId ) {
2123 $firstUnknownArgType = $argId;
2126 $csharpArg = ($arg->{ArgName
} eq "" ?
"arg" . $argId : $arg->{ArgName
});
2127 $csharpArgType = cplusplusToCSharp
($argType);
2129 # if ( $csharpArgType =~ /StringBuilder/ && $classNode->{astNodeName} ne $main::globalSpaceClassName) {
2130 # $addImport->{"System.Text"} = 1;
2132 if ( $classNode->{astNodeName
} eq 'Qt' or $classNode->{astNodeName
} eq 'KDE' ) {
2133 $addImport->{"System.Collections.Generic"} = 1;
2136 push @argTypeList, $argType;
2137 push @csharpArgTypeOnlyList, $csharpArgType;
2138 push @csharpArgTypeList, $csharpArgType . " " . $csharpArg;
2140 # Detect objects passed by value
2141 if ($classNode->{astNodeName
} ne $main::globalSpaceClassName
) {
2142 checkImportsForObject
( $argType, $addImport, $classNode );
2146 if ( $name eq 'QApplication' or ($csharpClassName eq 'KCmdLineArgs' and $name eq 'init' and scalar(@csharpArgTypeList) > 1) ) {
2147 # Junk the 'int argc' parameter
2148 shift @csharpArgTypeList;
2149 shift @csharpArgTypeOnlyList;
2152 my @castedArgList = makeCastedArgList
( @argTypeList );
2154 # We iterate as many times as we have default params
2155 my $firstDefaultParam = $m->{FirstDefaultParam
};
2156 $firstDefaultParam = scalar(@argTypeList) unless defined $firstDefaultParam;
2157 my $iterationCount = scalar(@argTypeList) - $firstDefaultParam;
2159 my $csharpReturnType = cplusplusToCSharp
($m->{ReturnType
});
2160 $csharpReturnType =~ s/^(out) |(ref) //;
2161 $csharpReturnType =~ s/StringBuilder/string/;
2163 if ($m->{ReturnType
} =~ /^int\&/) {
2164 $csharpReturnType = 'int';
2167 if ($csharpReturnType eq "") {
2168 $firstUnknownArgType = 0;
2171 print STDERR
" ". ($iterationCount+1). " iterations for $name\n" if ($debug);
2173 my $csharpSignature = csharpMethodSignature
( $m, @argTypeList );
2175 if ( defined $csharpMethods->{$csharpSignature} ) {
2176 $hasDuplicateSignature = 1;
2179 my $docnode = $m->{DocNode
};
2180 if ( $firstUnknownArgType >= 0 && $m->{Access
} !~ /signals/ && ! $hasDuplicateSignature
2181 && $classNode->{astNodeName
} ne $main::globalSpaceClassName
2182 && defined $docnode && ($generateConstructors || !$isConstructor) )
2184 my $csharpdocComment = printCSharpdocComment
( $docnode, "", "\t\t/// ", "" );
2186 $staticMethodCode .= $csharpdocComment unless $csharpdocComment =~ /^\s*$/;
2188 $methodCode .= $csharpdocComment unless $csharpdocComment =~ /^\s*$/;
2192 while($iterationCount >= 0) {
2194 $csharpMethods->{$csharpSignature} = 1;
2197 my $argsSignature = argsSignature( $m, $#argTypeList );
2198 my $signature = methodSignature( $m, $#argTypeList );
2199 my $mungedSignature = mungedSignature( $m, $#argTypeList );
2200 my $mungedMethod = $m->{astNodeName} . $mungedSignature;
2201 my $csharpparams = join( ", ", @csharpArgTypeList );
2203 # Ignore any methods in QGlobalSpace except those that are operator methods
2204 # with at least one arg that is the type of the current class
2205 if ( $classNode->{astNodeName} eq $main::globalSpaceClassName
2206 && $csharpClassName ne 'Qt'
2207 && $csharpClassName ne 'KDE'
2208 && !( $name =~ /^operator.*/
2209 && $name ne 'operator<<'
2210 && $name ne 'operator>>'
2211 && $csharpparams =~ /$csharpClassName / ) )
2214 } elsif ($firstUnknownArgType <= scalar(@argTypeList) || $hasDuplicateSignature || ($name =~ /^qObject$/) || $m->{Access} =~ /dcop/ || $name =~ ?[|&*/+^-]=? ) {
2215 if ( $firstUnknownArgType <= scalar(@argTypeList) || $m->{Access} =~ /dcop/ || $name =~ ?[|&*/+^-]=? ) {
2216 my $failedConversion = "\t\t// " . $m->{ReturnType} . " $name(@castedArgList[0..$#argTypeList]); >>>> NOT CONVERTED
\n";
2217 if ( $m->{Access} =~ /signals/ ) {
2218 $signalCode .= $failedConversion;
2220 $notConverted .= $failedConversion;
2225 if ( $csharpReturnType =~ s/string\[\]/ArrayList/ ) {
2226 $addImport->{"System
.Collections
"} = 1;
2229 if ( $csharpReturnType =~ s/string\[\]/List<string>/ ) {
2230 $addImport->{"System
.Collections
.Generic
"} = 1;
2233 my $cplusplusparams;
2235 for my $arg (@argTypeList) {
2236 $cplusplusparams .= "," if $i++;
2237 $cplusplusparams .= "arg
" . $i;
2240 my $access = $m->{Access};
2241 $access =~ s/_slots//;
2243 if ($isConstructor) {
2244 if ( $generateConstructors ) {
2245 # $proxyInterfaceCode .= "\t\t\tvoid new
$csharpClassName($csharpparams);\n";
2246 $methodCode .= "\t\tpublic
$csharpClassName($csharpparams) : this
((Type
) null
) {\n";
2247 $methodCode .= "\t\t\tCreateProxy
();\n";
2248 $methodCode .= smokeInvocation("interceptor
", \@csharpArgTypeList, "void
", $mungedMethod, $signature, $addImport);
2249 $methodCode .= "\t\t}\n";
2251 } elsif ( $mainClassNode->{Pure} && $isPure ) {
2252 if ( $#argTypeList == $#{$m->{ParamList}} ) {
2253 if ($name =~ /^sizeHint$/) {
2254 # This method is public in some places, but protected in others,
2255 # so make them all public.
2259 if ($name =~ /^([a-z])(.*)/) {
2260 $name = uc($1) . $2;
2263 if ($access eq 'public' && ! $isStatic) {
2264 $interfaceCode .= "\t\t$csharpReturnType $name($csharpparams);\n";
2267 # Only change the method name to start with an upper case letter
2268 # if it doesn't clash with an enum with the same name
2269 my $item = kdocAstUtil::findRef( $classNode, $name );
2270 if ( defined $item && $item->{NodeType} eq 'enum' && $name =~ /^([A-Z])(.*)/) {
2271 $name = lc($1) . $2;
2274 $methodCode .= "\t\t\
[SmokeMethod
(\"$signature\")]\n";
2276 if ( defined $virtualMethods->{$fullSignature}{method}
2277 || defined $overridenMethods->{$signature}{method}
2278 || (defined $overridenMethods->{$name}{method}) )
2280 if ($csharpClassName eq 'QLayout' && $name eq 'SetGeometry') {
2281 $methodCode .= "\t\t" . $access . " abstract
";
2283 $methodCode .= "\t\t" . $access . " new abstract
";
2286 $methodCode .= "\t\t" . $access . " abstract
";
2289 $methodCode .= $csharpReturnType;
2290 $methodCode .= " $name($csharpparams);\n";
2292 } elsif ( $name =~ /^operator.*/ && $name ne 'operator<<' && $name ne 'operator>>') {
2294 $name =~ s!([|&*/+^-])=!$1!;
2295 if ( $csharpSignature =~ s!([|&*/+^-])=!$1! ) {
2296 if ( $csharpMethods->{$csharpSignature} ) {
2297 print("dup method found
: $csharpSignature\n");
2299 $csharpMethods->{$csharpSignature} = 1;
2302 # In C# operator methods must be static, so if the C++ version isn't
2303 # static, then add another arg 'lhs', the value of 'this'.
2304 $csharpparams = "$csharpClassName lhs
" . ($csharpparams eq "" ? "" : ", ") . $csharpparams;
2305 unshift @csharpArgTypeList, "$csharpClassName lhs
";
2306 unshift @csharpArgTypeOnlyList, $csharpClassName;
2307 $csharpSignature =~ s/\(/($csharpClassName, /;
2308 $csharpSignature =~ s/, \)/)/;
2309 if ( $csharpMethods->{$csharpSignature} ) {
2310 print("dup method found
: $csharpSignature\n");
2312 $csharpMethods->{$csharpSignature} = 1;
2315 if ( $classNode->{astNodeName} ne $main::globalSpaceClassName
2316 || (@csharpArgTypeOnlyList[0] eq $csharpClassName || @csharpArgTypeOnlyList[1] eq $csharpClassName) )
2318 $proxyInterfaceCode .= "\t\t\t$csharpReturnType $operatorNames{$name}($csharpparams);\n";
2320 $staticMethodCode .= "\t\t" . $access . " static
";
2321 $staticMethodCode .= $csharpReturnType;
2323 $staticMethodCode .= " $name($csharpparams) \
{\n";
2324 $staticMethodCode .= smokeInvocation("staticInterceptor
", \@csharpArgTypeList, $csharpReturnType, $mungedMethod, $signature, $addImport);
2325 $staticMethodCode .= "\t\t}\n";
2328 if ( $name =~ /operator==/
2329 && ( @csharpArgTypeOnlyList[0] eq $csharpClassName || @csharpArgTypeOnlyList[1] eq $csharpClassName )
2330 && $csharpClassName ne 'Qt'
2331 && $csharpClassName ne 'KDE' )
2333 # Add a 'operator!=' method defined in terms of 'operator=='
2334 $staticMethodCode .= "\t\t" . $access . " static bool
";
2335 $staticMethodCode .= " operator
!=($csharpparams) \
{\n";
2337 $staticMethodCode .= "\t\t\treturn
";
2338 $staticMethodCode .= "!(bool
) staticInterceptor
.Invoke
(\"$mungedMethod\", \"$signature\", typeof
($csharpReturnType)". smokeInvocationArgList(\@csharpArgTypeList) . ");\n";
2339 $staticMethodCode .= "\t\t}\n";
2341 if (!defined $mainClassNode->{HasEquals}) {
2342 $methodCode .= "\t\tpublic override bool Equals
(object o
) \
{\n";
2343 $methodCode .= "\t\t\tif
(!(o is
$csharpClassName)) { return false
; }\n";
2345 $methodCode .= "\t\t\treturn this
== ($csharpClassName) o
;\n";
2346 $methodCode .= "\t\t}\n";
2348 $methodCode .= "\t\tpublic override
int GetHashCode
() \
{\n";
2349 $methodCode .= "\t\t\treturn interceptor
.GetHashCode
();\n";
2350 $methodCode .= "\t\t}\n";
2351 $mainClassNode->{HasEquals} = 1;
2355 if ( $name =~ /^operator\s*<$/
2356 && $classNode->{astNodeName} ne $main::globalSpaceClassName )
2358 my $item = kdocAstUtil::findRef( $classNode, "operator
>" );
2359 if (! defined $item || $item->{Parent}->{astNodeName} eq 'Global') {
2360 $staticMethodCode .= "\t\t" . $access . " static bool
";
2361 $staticMethodCode .= " operator
>($csharpparams) \
{\n";
2363 $staticMethodCode .= "\t\t\treturn
";
2364 $staticMethodCode .= "!(bool
) staticInterceptor
.Invoke
(\"$mungedMethod\", \"$signature\", typeof
($csharpReturnType)". smokeInvocationArgList(\@csharpArgTypeList) . ")\n";
2365 $staticMethodCode .= "\t\t\t\t\t\t&& !(bool
) staticInterceptor
.Invoke
(\"operator
==$mungedSignature\", \"operator
==$argsSignature\", typeof
($csharpReturnType)". smokeInvocationArgList(\@csharpArgTypeList) . ");\n";
2366 $staticMethodCode .= "\t\t}\n";
2370 if ( $access eq 'public' or $access eq 'protected' ) {
2371 if ( ($csharpClassName eq 'QHeaderView' && $name =~ /^scrollTo$|^indexAt$|^visualRect$/)
2372 || ($csharpClassName eq 'QSvgGenerator' && $name =~ /^paintEngine$/)
2373 || ($csharpClassName eq 'QGridLayout' && $name =~ /^addItem$/)
2374 || ($csharpClassName eq 'QGraphicsWidget' && $name =~ /^updateGeometry$/)
2375 || $name =~ /^sizeHint$/ )
2377 # These methods are public in some places, but protected in others,
2378 # so make them all public.
2382 if ($name eq 'operator<<' || $name eq 'operator>>') {
2383 # 'operator<<' and 'operator>>' can only have int types as the second
2384 # arg in C#, so convert them to op_read() and op_write() calls
2385 $name = $operatorNames{$name}
2386 } elsif ($name =~ /^([a-z])(.*)/) {
2387 if ($name ne 'type') {
2388 $name = uc($1) . $2;
2391 # Only constructors can have the same name as the class
2392 if ( $name eq $csharpClassName || $name eq 'Transition' ) {
2393 $name = lc($1) . $2;
2396 # Only change the method name to start with an upper case letter
2397 # if it doesn't clash with an enum with the same name
2398 my $item = kdocAstUtil::findRef( $classNode, $name );
2399 if ( defined $item && $item->{NodeType} eq 'enum' && $name =~ /^([A-Z])(.*)/) {
2400 $name = lc($1) . $2;
2403 $item = kdocAstUtil::findRef( $classNode, "Q_PROPERTY_
" . $m->{astNodeName} );
2404 if ( defined $item && $item->{NodeType} eq 'property' ) {
2405 # If there is a property with the same name, start with lower case
2406 $name = lc($1) . $2;
2409 if ($classNode->{astNodeName} eq 'QIODevice' and $name eq 'State') {
2414 if ($access eq 'public' && ! $isStatic) {
2415 $interfaceCode .= "\t\t$csharpReturnType $name($csharpparams);\n";
2418 if (($isStatic or $classNode->{NodeType} eq 'namespace')) {
2419 $proxyInterfaceCode .= "\t\t\t$csharpReturnType $name($csharpparams);\n";
2422 if ( $m->{Access} =~ /_slots/ && !$isStatic ) {
2423 $methodCode .= "\t\t[Q_SLOT
(\"". $m->{ReturnType} . " $signature" . "\")]\n";
2426 my $overridenVirtualMethod = $virtualMethods->{$signature}{method};
2427 $virtualMethods->{$signature}{method} = undef;
2428 my $overridenMethod = $overridenMethods->{$signature}{method};
2430 if (defined $overridenVirtualMethod || $m->{Flags} =~ "v
") {
2431 $methodCode .= "\t\t\
[SmokeMethod
(\"$signature\")]\n";
2434 if ($isStatic or $classNode->{NodeType} eq 'namespace') {
2435 $staticMethodCode .= "\t\t$access static
";
2437 $methodCode .= "\t\t$access ";
2440 if ( ($name eq 'ToString' && $csharpparams eq '')
2441 || ( ($csharpClassName =~ /^QGraphicsSvgItem$|^QGraphicsTextItem$/)
2442 && ($name eq 'Children' || $name eq 'InputMethodQuery') ) )
2444 # Tricky. QGraphicsSvgItem and QGraphicsTextItem inherit a 'children()' method from both
2445 # of their parents, and so is it resolved on the return type in C++?
2446 $methodCode .= "new
";
2447 } elsif ( defined $overridenVirtualMethod ) {
2448 # Only change the method name to start with an upper case letter
2449 # if it doesn't clash with an enum with the same name
2450 my $overrideClass = $virtualMethods->{$fullSignature}{class};
2452 # Special case looking for QStyle name clashes with methods/enums
2453 if ($csharpClassName =~ /Style/) {
2454 $overrideClass = kdocAstUtil::findRef( $rootnode, "QStyle
" );
2457 my $item = kdocAstUtil::findRef( $overrideClass, $name );
2458 if ( defined $item && $item->{NodeType} eq 'enum' && $name =~ /^([A-Z])(.*)/) {
2459 $name = lc($1) . $2;
2462 $item = kdocAstUtil::findRef( $overrideClass, "Q_PROPERTY_
" . $m->{astNodeName} );
2463 if ( defined $item && $item->{NodeType} eq 'property' ) {
2464 # If there is a property with the same name, start with lower case
2465 $name = lc($1) . $2;
2468 if ( $overridenVirtualMethod->{Flags} !~ "p
"
2469 && ( ($overridenVirtualMethod->{Access} =~ /public/ && $m->{Access} =~ /protected/)
2470 || ($overridenVirtualMethod->{Access} =~ /protected/ && $m->{Access} =~ /public/) ) )
2472 $methodCode .= "new virtual
";
2473 } elsif ( !defined $overridenVirtualMethod->{FirstDefaultParam}
2474 && $#argTypeList < $#{$overridenVirtualMethod->{ParamList}} )
2477 } elsif ( defined $overridenVirtualMethod->{FirstDefaultParam}
2478 && $overridenVirtualMethod->{Flags} =~ "p
"
2479 && $#argTypeList < $#{$overridenVirtualMethod->{ParamList}} )
2481 $methodCode .= "virtual
";
2482 } elsif ( $csharpClassName eq 'QAbstractListModel' && $name eq 'Index' && $#argTypeList == 0) {
2484 } elsif ( $ancestorCount == 0
2485 || ( $ancestorCount > 1
2486 && defined $interfacemap{$overridenVirtualMethod->{Parent}->{astNodeName}} ) )
2488 $methodCode .= "virtual
";
2489 } elsif ($overridenVirtualMethod->{Flags} =~ "p
") {
2490 $methodCode .= "override
";
2492 $methodCode .= "override
";
2494 } elsif ($m->{Flags} =~ "v
") {
2495 if (defined $overridenMethods->{$name}{method}) {
2496 $methodCode .= "new virtual
";
2498 $methodCode .= "virtual
";
2500 } elsif ( defined $overridenMethod ) {
2502 $staticMethodCode .= "new
";
2503 } elsif ( $ancestorCount == 1
2504 || !defined $interfacemap{$overridenMethod->{Parent}->{astNodeName}} )
2506 $methodCode .= "new
";
2508 } elsif ( defined $overridenMethods->{$name}{method} ) {
2509 $methodCode .= "new
";
2512 if ( $name eq 'Exec'
2513 && ($csharpClassName eq 'QApplication' || $csharpClassName eq 'QCoreApplication') )
2515 $staticMethodCode .= $csharpReturnType;
2516 $staticMethodCode .= " $name($csharpparams) \
{\n";
2517 $staticMethodCode .= "\t\t\tint result
= (int) staticInterceptor
.Invoke
(\"exec\", \"exec()\", typeof
(int));\n";
2518 $staticMethodCode .= "\t\t\tQyoto
.SetApplicationTerminated
();\n";
2519 $staticMethodCode .= "\t\t\treturn result
;\n";
2520 $staticMethodCode .= "\t\t}\n";
2521 } elsif ($isStatic or $classNode->{NodeType} eq 'namespace') {
2522 $staticMethodCode .= $csharpReturnType;
2523 $staticMethodCode .= " $name($csharpparams) \
{\n";
2524 $staticMethodCode .= smokeInvocation("staticInterceptor
", \@csharpArgTypeList, $csharpReturnType, $mungedMethod, $signature, $addImport);
2525 $staticMethodCode .= "\t\t}\n";
2527 $methodCode .= $csharpReturnType;
2528 $methodCode .= " $name($csharpparams) \
{\n";
2529 $methodCode .= smokeInvocation("interceptor
", \@csharpArgTypeList, $csharpReturnType, $mungedMethod, $signature, $addImport);
2530 $methodCode .= "\t\t}\n";
2533 if ( $access =~ /signals/ ) {
2534 if ($name =~ /^([a-z])(.*)/) {
2535 $name = uc($1) . $2;
2537 my $docnode = $m->{DocNode};
2538 if ( defined $docnode ) {
2539 my $csharpdocComment = printCSharpdocComment( $docnode, "", "\t\t/// ", "" );
2540 $signalCode .= $csharpdocComment unless $csharpdocComment =~ /^\s*$/;
2542 $signalCode .= "\t\t[Q_SIGNAL
(\"" . $m->{ReturnType} . " $signature" . "\")]\n";
2543 $signalCode .= "\t\tvoid
$name($csharpparams);\n";
2550 pop @csharpArgTypeList;
2551 pop @csharpArgTypeOnlyList;
2553 $csharpSignature = csharpMethodSignature( $m, @argTypeList );
2554 $hasDuplicateSignature = (defined $csharpMethods->{$csharpSignature} ? 1 : 0);
2560 return ( $methodCode, $staticMethodCode, $interfaceCode, $proxyInterfaceCode, $signalCode, $notConverted );
2563 sub resolveEnumValue($$)
2565 my ( $enumClass, $enumValue ) = @_;
2567 my $classNode = kdocAstUtil::findRef( $rootnode, $enumClass );
2570 Iter::MembersByType ( $classNode, undef,
2571 sub { my ($classNode, $enumNode ) = @_;
2573 if ( $enumNode->{NodeType} eq 'enum' ) {
2574 my @enums = split(",", $enumNode->{Params});
2575 foreach my $enum ( @enums ) {
2576 if ($enum =~ /^\s*(\w+)/) {
2577 if ($1 eq $enumValue) {
2578 $enumType = $enumNode->{astNodeName};
2585 if (defined $enumType) {
2586 $enumType =~ s/^Type$/TypeOf/;
2587 return "$enumClass.$enumType.$enumValue";
2589 return "$enumClass.$enumValue";
2593 sub generateEnum($$$)
2595 my( $classNode, $m, $generateAnonymous ) = @_; # input
2596 my $methodCode = ''; # output
2598 my @heritage = kdocAstUtil::heritage($classNode);
2599 my $className = join( "::", @heritage );
2600 my $csharpClassName = $classNode->{astNodeName};
2602 if ( ($generateAnonymous and $m->{astNodeName} ) or (! $generateAnonymous and ! $m->{astNodeName}) ) {
2606 if ( defined $m->{DocNode} ) {
2607 my $csharpdocComment = printCSharpdocComment( $m->{DocNode}, "", "\t/// ", "" );
2608 $methodCode .= $csharpdocComment unless $csharpdocComment =~ /^\s*$/;
2611 # In C# enums must have names, so anonymous C++ enums become constants
2612 if (! $m->{astNodeName}) {
2613 return generateConst($classNode, $m, $generateAnonymous);
2616 $m->{astNodeName} =~ /(.)(.*)/;
2618 # my $item = kdocAstUtil::findRef( $classNode, lc($1) . $2 );
2619 if ( $m->{astNodeName} eq 'Type') {
2620 # Enums and capitalized method names share the same namespace in C#, so add
2621 # 'E_' to the front to avoid a clash.
2622 $methodCode .= "\tpublic enum TypeOf
{\n";
2623 } elsif ( $m->{astNodeName} eq 'ConversionFlag'
2624 || ($classNode->{astNodeName} eq 'QTextOption' and $m->{astNodeName} eq 'Flag')
2625 || ($classNode->{astNodeName} eq 'Qt' and $m->{astNodeName} eq 'Modifier')
2626 || ($classNode->{astNodeName} eq 'QGraphicsItem' and $m->{astNodeName} eq 'Extension')
2627 || ($classNode->{astNodeName} eq 'QAccessible' and $m->{astNodeName} eq 'StateFlag')
2628 || ($classNode->{astNodeName} eq 'Qt' and $m->{astNodeName} eq 'KeyboardModifier') )
2630 $methodCode .= "\tpublic enum
" . $m->{astNodeName} . " : long
{\n";
2632 $methodCode .= "\tpublic enum
" . $m->{astNodeName} . " {\n";
2635 my @enums = split(",", $m->{Params});
2637 foreach my $enum ( @enums ) {
2639 if ($enum =~ /.*\s(\w*)::(\w*)/) {
2640 my $result = resolveEnumValue($1, $2);
2641 $enum =~ /(.*\s)(\w*)::(\w*)(.*)/;
2642 if ( $className eq 'KProtocolInfo::ExtraField' && $m->{astNodeName} eq 'Type' ) {
2643 $enum = $1 . "(int) " . $result . $4;
2645 $enum = $1 . $result . $4;
2650 if ($m->{astNodeName} ne 'KeyboardModifier') {
2651 $enum =~ s/KeyboardModifierMask/KeyboardModifier.KeyboardModifierMask/;
2654 if ($m->{astNodeName} ne 'PolicyFlag') {
2655 $enum =~ s/GrowFlag/PolicyFlag.GrowFlag/;
2656 $enum =~ s/ExpandFlag/PolicyFlag.ExpandFlag/;
2657 $enum =~ s/ShrinkFlag/PolicyFlag.ShrinkFlag/;
2658 $enum =~ s/IgnoreFlag/PolicyFlag.IgnoreFlag/;
2663 $enum =~ s/::([a-z])/./g;
2664 $enum =~ s/\.\././g;
2665 $enum =~ s/\(mode_t\)//;
2666 $enum =~ s/internal/_internal/;
2667 $enum =~ s/fixed/_fixed/;
2668 $enum =~ s/sizeof\(void\*\)/4/;
2669 if ( $enum =~ /(.*)=([-0-9]+)$/ ) {
2670 $methodCode .= "\t\t$1 = $2,\n";
2673 } elsif ( $enum =~ /(.*)=(.*)/ ) {
2676 $value =~ s/^MAX_INT$/2147483647/;
2677 $value =~ s/^SO_/QStyleOption.OptionType.SO_/;
2678 if ($classNode->{astNodeName} eq 'QStyleHintReturn' || $classNode->{astNodeName} eq 'QStyleHintReturnMask') {
2679 $value =~ s/^SH_/QStyleHintReturn.HintReturnType.SH_/;
2680 } elsif ($classNode->{astNodeName} eq 'QStyle') {
2681 $value =~ s/^SH_/QStyle.StyleHint.SH_/;
2684 $methodCode .= "\t\t$name = $value,\n";
2685 if ($value =~ /(0xf0000000)|(0xffffffff)|(0xF0000000)|(0xFFFFFFFF)/) {
2686 $methodCode =~ s/enum ((E_)?[^\s]*)/enum $1 : uint/;
2689 $methodCode .= "\t\t$enum = $enumCount,\n";
2694 $methodCode .= "\t}\n";
2697 return ( $methodCode );
2700 sub generateConst($$$)
2702 my( $classNode, $m, $generateAnonymous ) = @_; # input
2703 my $methodCode = ''; # output
2705 my @heritage = kdocAstUtil::heritage($classNode);
2706 my $className = join( "::", @heritage );
2707 my $csharpClassName = $classNode->{astNodeName};
2709 my @enums = split(",", $m->{Params});
2711 foreach my $enum ( @enums ) {
2714 $enum =~ s/\(mode_t\)//;
2715 $enum =~ s/internal/_internal/;
2716 $enum =~ s/fixed/_fixed/;
2717 $enum =~ s/IsActive/_IsActive/;
2719 if ($enum =~ /(.*)=(0[xX][fF][0-9a-fA-F]{7})$/) {
2720 $methodCode .= "\t\tpublic const long
$1 = $2;\n";
2721 } elsif ( $enum =~ /(.*)=([-0-9]+)$/ ) {
2723 && $classNode->{astNodeName} ne 'QGraphicsItem'
2724 && $classNode->{astNodeName} ne 'QGraphicsTextItem'
2725 && $classNode->{astNodeName} ne 'QGraphicsSvgItem' )
2727 $methodCode .= "\t\tpublic new const
int $1 = $2;\n";
2729 $methodCode .= "\t\tpublic const
int $1 = $2;\n";
2733 } elsif ( $enum =~ /(.*)=.*static_cast<.*>\((.*)\)/ ) {
2734 $methodCode .= "\t\tpublic const
int $1 = $2;\n";
2735 } elsif ( $enum =~ /(.*)=(.*)/ ) {
2738 if ($value =~ /\s*(\w*)\.(\w*)/) {
2739 $value = "(int) " . resolveEnumValue($1, $2);
2742 $value =~ s/^MAX_INT$/2147483647/;
2743 $methodCode .= "\t\tpublic const
int $name = $value;\n";
2745 $methodCode .= "\t\tpublic const
int $enum = $enumCount;\n";
2752 return ( $methodCode );
2755 sub generateVar($$$)
2757 my( $classNode, $m, $addImport ) = @_; # input
2758 my $methodCode = ''; # output
2759 my $interfaceCode = ''; # output
2760 my $proxyInterfaceCode = ''; # output
2762 my @heritage = kdocAstUtil::heritage($classNode);
2763 my $className = join( "::", @heritage );
2764 my $csharpClassName = $classNode->{astNodeName};
2766 my $name = $m->{astNodeName};
2767 my $varType = $m->{Type};
2768 $varType =~ s/static\s//;
2769 $varType =~ s/const\s+(.*)\s*&/$1/;
2770 $varType =~ s/\s*$//;
2771 my $fullName = "$className\
::$name";
2772 $varType = cplusplusToCSharp($varType);
2773 if (!defined $varType) {
2774 return ( $methodCode, $interfaceCode, $proxyInterfaceCode );
2777 checkImportsForObject( $varType, $addImport, $classNode );
2779 my $propertyName = $name;
2780 if ( $propertyName =~ /^([a-z])(.*)/) {
2781 $propertyName = uc($1) . $2;
2784 if ( $m->{Flags} =~ "s
" ) {
2785 $methodCode .= "\t\tpublic static
$varType $propertyName() {\n";
2786 $methodCode .= "\t\t\treturn
($varType) staticInterceptor
.Invoke
(\"$name\", \"$name()\", typeof
($varType));\n";
2787 $methodCode .= "\t\t}\n";
2788 $proxyInterfaceCode .= "\t\t\t$varType $name();\n";
2790 # $methodCode .= "\t\tprivate
$varType $name() {\n";
2791 # $methodCode .= "\t\t\treturn
($varType) interceptor
.Invoke
(\"$name\", \"$name()\", typeof
($varType));\n";
2792 # $methodCode .= "\t\t}\n";
2793 $methodCode .= "\t\tpublic
$varType $propertyName {\n";
2794 $methodCode .= "\t\t\tget
{ return ($varType) interceptor
.Invoke
(\"$name\", \"$name()\", typeof
($varType)); }\n";
2795 $methodCode .= "\t\t}\n";
2796 $interfaceCode .= "\t\t". cplusplusToCSharp($varType) . " $name();\n";
2800 return ( $methodCode, $interfaceCode, $proxyInterfaceCode );
2803 sub generateProperty($$$$)
2805 my( $overridenMethods, $classNode, $m, $addImport ) = @_; # input
2806 my $methodCode = ''; # output
2808 my @heritage = kdocAstUtil::heritage($classNode);
2809 my $className = join( "::", @heritage );
2810 my $csharpClassName = $classNode->{astNodeName};
2812 my $name = $m->{astNodeName};
2814 my $resolvedType = kalyptusDataDict::resolveType($m->{Type}, $classNode, $rootnode);
2815 my $propertyType = cplusplusToCSharp( $resolvedType );
2816 if ( ! defined $propertyType ) {
2817 return ( $methodCode );
2820 checkImportsForObject( $m->{Type}, $addImport, $classNode );
2822 $name =~ s/Q_PROPERTY_//;
2823 my $propertyName = $name;
2824 if ( $propertyName =~ /^([a-z])(.*)/ && $propertyName ne 'icon') {
2825 $propertyName = uc($1) . $2;
2828 # Only change the method name to start with an upper case letter
2829 # if it doesn't clash with an enum with the same name
2830 my $uppercaseItem = kdocAstUtil::findRef( $classNode, $propertyName );
2831 if (defined $uppercaseItem && $uppercaseItem->{NodeType} eq 'enum' && $propertyName =~ /^([A-Z])(.*)/) {
2832 $propertyName = lc($1) . $2;
2835 $methodCode .= "\t\t[Q_PROPERTY
(\"$resolvedType\", \"$name\")]\n";
2837 if ( defined $overridenMethods->{$propertyName}{method} ) {
2838 $methodCode .= "\t\tpublic new
$propertyType $propertyName {\n";
2840 $methodCode .= "\t\tpublic
$propertyType $propertyName {\n";
2843 if ( defined $m->{READ} ) {
2844 $methodCode .= "\t\t\tget
{ return ($propertyType) interceptor
.Invoke
(\"$m->{READ
}\", \"$m->{READ
}()\", typeof
($propertyType)); }\n";
2847 if ( defined $m->{WRITE} ) {
2848 $methodCode .= "\t\t\tset
{ interceptor
.Invoke
(\"$m->{WRITE
}" . mungedArgType($m, $resolvedType) . "\", \"$m->{WRITE
}($resolvedType)\", typeof
(void
), typeof
($propertyType), value
); }\n";
2851 $methodCode .= "\t\t}\n";
2853 return ( $methodCode );
2856 ## Called by writeClassDoc
2857 sub generateAllMethods($$$$$$)
2859 my ($classNode, $ancestorCount, $csharpMethods, $mainClassNode, $generateConstructors, $addImport) = @_;
2860 my $methodCode = '';
2861 my $staticMethodCode = '';
2862 my $interfaceCode = '';
2863 my $proxyInterfaceCode = '';
2864 my $signalCode = '';
2865 my $notConverted = '';
2869 my $className = join( "::", kdocAstUtil::heritage($classNode) );
2870 my $csharpClassName = $mainClassNode->{astNodeName};
2871 # If the C++ class had multiple inheritance, then the code for all but one of the
2872 # parents must be copied into the code for csharpClassName. Hence, for QWidget current
2873 # classname might be QPaintDevice, as its methods are needed in QWidget.
2874 my $currentClassName = join( ".", kdocAstUtil::heritage($classNode) );
2876 my $sourcename = $classNode->{Source}->{astNodeName};
2878 if ( $sourcename !~ s!.*(kio/|kparts/|dom/|kabc/|ksettings/|kjs/|ktexteditor/|kdeprint/|kdesu/)(.*)!$1$2!m ) {
2879 $sourcename =~ s!.*/(.*)!$1!m;
2881 die "Empty source name
for $classNode->{astNodeName
}" if ( $sourcename eq '' );
2883 $addImport->{"Qyoto
"} = 1;
2884 if ($className =~ /^Plasma::/) {
2885 $addImport->{"Kimono
"} = 1;
2889 allVirtualMethods( $classNode, \%virtualMethods, $classNode );
2891 my %overridenMethods;
2892 allOverridenMethods( $classNode, \%overridenMethods, $classNode );
2894 for my $sig (keys %overridenMethods) {
2895 # print("$currentClassName sig
: $overridenMethods{$sig}{class}->{astNodeName
}::$sig\n");
2898 Iter::MembersByType ( $classNode, undef,
2899 sub { my ($classNode, $methodNode ) = @_;
2901 if ( $methodNode->{NodeType} eq 'enum' and $classNode->{astNodeName} eq $mainClassNode->{astNodeName} ) {
2902 my ($code) = generateEnum( $classNode, $methodNode, 0 );
2907 # Do all enums first, anonymous ones and then named enums
2908 Iter::MembersByType ( $classNode, undef,
2909 sub { my ($classNode, $methodNode ) = @_;
2911 if ( $methodNode->{NodeType} eq 'enum' and $classNode->{astNodeName} eq $mainClassNode->{astNodeName} ) {
2912 my ($code) = generateEnum( $classNode, $methodNode, 1 );
2913 $extraCode .= $code;
2917 # Then all static vars
2918 Iter::MembersByType ( $classNode, undef,
2919 sub { my ($classNode, $methodNode ) = @_;
2921 if ( $methodNode->{NodeType} eq 'var' and $classNode->{astNodeName} eq $mainClassNode->{astNodeName} ) {
2922 my ($code, $interface, $proxyInterface) = generateVar( $classNode, $methodNode, $addImport );
2923 $extraCode .= $code;
2924 $interfaceCode .= $interface;
2925 $proxyInterfaceCode .= $proxyInterface;
2929 # Then all properties
2930 Iter::MembersByType ( $classNode, undef,
2931 sub { my ($classNode, $methodNode ) = @_;
2933 if ( $methodNode->{NodeType} eq 'property' and $classNode->{astNodeName} eq $mainClassNode->{astNodeName} ) {
2934 my ($code, $interface) = generateProperty( \%overridenMethods, $classNode, $methodNode, $addImport );
2935 $extraCode .= $code;
2940 Iter::MembersByType ( $classNode, undef,
2941 sub { my ($classNode, $methodNode ) = @_;
2943 if ( $methodNode->{NodeType} eq 'method' ) {
2944 my ($meth, $static, $interface, $proxyInterface, $signals, $notconv) = generateMethod( \%virtualMethods, \%overridenMethods, $classNode, $methodNode, $addImport, $ancestorCount, $csharpMethods, $mainClassNode, $generateConstructors );
2945 $methodCode .= $meth;
2946 $staticMethodCode .= $static;
2947 $interfaceCode .= $interface;
2948 $proxyInterfaceCode .= $proxyInterface;
2949 $signalCode .= $signals;
2950 $notConverted .= $notconv;
2954 for my $sig (keys %virtualMethods) {
2955 if ( $virtualMethods{$sig}{method}->{Flags} =~ /[p]/
2956 && $classNode->{astNodeName} ne $virtualMethods{$sig}{class}->{astNodeName}
2957 && ! exists $classNode->{Pure} )
2959 # If a pure virtual method in the superclass hasn't been overriden, then C++ will
2960 # assume it is still ok to instantiate instances of the class as long as it hasn't got
2961 # its own pure virtual methods. However, in C# this isn't allowed, and so we need
2962 # to add 'dummy' method calls here to cover the non-overriden pure virtual methods,
2963 # and avoid needing to make the class abstract.
2964 my $docNode = $virtualMethods{$sig}{method}->{DocNode};
2965 $virtualMethods{$sig}{method}->{DocNode} = undef;
2966 my ($meth, $static, $interface, $proxyInterface, $signals, $notconv) = generateMethod( \%virtualMethods, \%overridenMethods, $classNode, $virtualMethods{$sig}{method}, $addImport, $ancestorCount, $csharpMethods, $mainClassNode, $generateConstructors );
2967 $virtualMethods{$sig}{method}->{DocNode} = $docNode;
2968 if ( $meth =~ /override/ ) {
2969 $methodCode .= "\t\t// WARNING
: Unimplemented C
++ pure virtual
- DO NOT CALL
\n";
2970 $methodCode .= $meth;
2971 $staticMethodCode .= $static;
2972 $interfaceCode .= $interface;
2973 $proxyInterfaceCode .= $proxyInterface;
2974 $signalCode .= $signals;
2975 $notConverted .= $notconv;
2980 if ( $classNode->{astNodeName} eq $csharpClassName
2981 && $classNode->{HasPublicDestructor}
2982 && $classNode->{CanBeInstanciated}
2983 && !$classNode->{Pure} )
2985 if ( $generateConstructors && $csharpClassName ne 'Qt' ) {
2986 $methodCode .= "\t\t~$csharpClassName() {\n";
2987 if ($csharpClassName eq 'QModelIndex') {
2988 $methodCode .= "\t\t\tQAbstractItemModel
.DerefIndexHandle
(InternalPointer
());\n";
2990 $methodCode .= "\t\t\tinterceptor
.Invoke
(\"~$classNode->{astNodeName
}\", \"~$classNode->{astNodeName
}()\", typeof
(void
));\n\t\t}\n";
2992 my $overridenMethod = $overridenMethods{~$classNode->{astNodeName}}{method};
2993 if ( defined $overridenMethod
2994 && $classNode->{astNodeName} ne 'QObject'
2995 && ( $ancestorCount == 1
2996 || !defined $interfacemap{$overridenMethod->{Parent}->{astNodeName}} ) )
2998 $methodCode .= "\t\tpublic new
";
3000 $methodCode .= "\t\tpublic
";
3002 $methodCode .= "void Dispose
() {\n";
3003 if ($csharpClassName eq 'QModelIndex') {
3004 $methodCode .= "\t\t\tQAbstractItemModel
.DerefIndexHandle
(InternalPointer
());\n";
3006 $methodCode .= "\t\t\tinterceptor
.Invoke
(\"~$classNode->{astNodeName
}\", \"~$classNode->{astNodeName
}()\", typeof
(void
));\n\t\t}\n";
3011 return ( $methodCode, $staticMethodCode, $interfaceCode, $proxyInterfaceCode, $signalCode, $extraCode, $enumCode, $notConverted );
3014 # Return 0 if the class has no virtual dtor, 1 if it has, 2 if it's private
3015 sub hasVirtualDestructor($$)
3017 my ( $classNode, $startNode ) = @_;
3018 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3019 return if ( $skippedClasses{$className} || defined $interfacemap{$className} );
3022 # Look at ancestors, and (recursively) call hasVirtualDestructor for each
3023 # It's enough to have one parent with a prot/public virtual dtor
3024 Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
3025 my $vd = hasVirtualDestructor( $_[0], $_[1] );
3026 $parentHasIt = $vd unless $parentHasIt > $vd;
3028 return $parentHasIt if $parentHasIt; # 1 or 2
3030 # Now look in $classNode - including private methods
3031 my $doPrivate = $main::doPrivate;
3032 $main::doPrivate = 1;
3034 Iter::MembersByType ( $classNode, undef,
3035 sub { my ($classNode, $m ) = @_;
3036 return unless( $m->{NodeType} eq "method
" && $m->{ReturnType} eq '~' );
3038 if ( $m->{Flags} =~ /[vp]/ && $classNode != $startNode) {
3039 if ( $m->{Access} =~ /private/ ) {
3040 $result=2; # private virtual
3042 $result=1; # [protected or public] virtual
3048 $main::doPrivate = $doPrivate;
3049 $result=0 if (!defined $result);
3053 =head2 allVirtualMethods
3055 Parameters: class node, dict
3057 Adds to the dict, for all method nodes that are virtual, in this class and in parent classes :
3058 {method} the method node, {class} the class node (the one where the virtual is implemented)
3062 sub allVirtualMethods($$$)
3064 my ( $classNode, $virtualMethods, $startNode ) = @_;
3065 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3066 return if ( $skippedClasses{$className} );
3068 # Look at ancestors, and (recursively) call allVirtualMethods for each
3069 # This is done first, so that virtual methods that are reimplemented as 'private'
3070 # can be removed from the list afterwards (below)
3071 Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
3072 allVirtualMethods( @_[0], $virtualMethods, $startNode );
3076 # Now look for virtual methods in $classNode - including private ones
3077 my $doPrivate = $main::doPrivate;
3078 $main::doPrivate = 1;
3079 Iter::MembersByType ( $classNode, undef,
3080 sub { my ($classNode, $m ) = @_;
3081 # Only interested in methods, and skip destructors
3082 return unless( $m->{NodeType} eq "method
" && $m->{ReturnType} ne '~' );
3084 my @args = @{ $m->{ParamList} };
3085 my $last = $m->{FirstDefaultParam};
3086 $last = scalar @args unless defined $last;
3087 my $iterationCount = scalar(@args) - $last;
3088 while($iterationCount >= 0) {
3089 my $signature = methodSignature( $m, $#args );
3090 print STDERR $signature . " ($m->{Access
})\n" if ($debug);
3092 # A method is virtual if marked as such (v=virtual p=pure virtual)
3093 # or if a parent method with same signature was virtual
3094 if ( $m->{Flags} =~ /[vp]/ or defined $virtualMethods->{$signature} ) {
3095 if ( $m->{Access} =~ /private/ ) {
3096 if ( defined $virtualMethods->{$signature} ) { # remove previously defined
3097 delete $virtualMethods->{$signature};
3099 # else, nothing, just ignore private virtual method
3100 } elsif ( $classNode->{astNodeName} ne $startNode->{astNodeName} ) {
3101 $virtualMethods->{$signature}{method} = $m;
3102 $virtualMethods->{$signature}{class} = $classNode;
3112 $main::doPrivate = $doPrivate;
3115 sub allOverridenMethods($$$)
3117 my ( $classNode, $overridenMethods, $startNode ) = @_;
3118 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3119 return if ( $skippedClasses{$className} );
3122 if ( $classNode->{astNodeName} eq 'QObject' ) {
3123 $qtnode = kdocAstUtil::findRef( $rootnode, "Qt
" );
3124 if ( defined $qtnode ) {
3125 allOverridenMethods( $qtnode, $overridenMethods, $startNode );
3129 Iter::Ancestors( $classNode, $qtnode, undef, undef, sub {
3130 allOverridenMethods( @_[0], $overridenMethods, $startNode );
3134 # Look at ancestors, and (recursively) call allOverridenMethods for each
3135 # This is done first, so that virtual methods that are reimplemented as 'private'
3136 # can be removed from the list afterwards (below)
3137 Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
3138 allOverridenMethods( @_[0], $overridenMethods, $startNode );
3142 # Now look for virtual methods in $classNode - including private ones
3143 Iter::MembersByType ( $classNode, undef,
3144 sub { my ($classNode, $m ) = @_;
3145 # Only interested in methods, and skip destructors
3146 return unless( $m->{NodeType} eq "method
" or $m->{NodeType} eq "enum
" or $m->{NodeType} eq "property
" );
3148 my $signature = methodSignature( $m, $#{$m->{ParamList}} );
3149 print STDERR $signature . " ($m->{Access
})\n" if ($debug);
3151 if ( $classNode->{astNodeName} ne $startNode->{astNodeName} && $classNode->{astNodeName} ne 'Global' ) {
3152 if ( $m->{NodeType} eq "enum
" ) {
3153 $overridenMethods->{$m->{astNodeName}}{method} = $m;
3154 $overridenMethods->{$m->{astNodeName}}{class} = $classNode;
3155 } elsif ( $m->{NodeType} eq "property
" ) {
3156 my $name = $m->{astNodeName};
3157 if ( $name =~ s/Q_PROPERTY_([a-z])(.*)// ) {
3158 $name = uc($1) . $2;
3161 $overridenMethods->{$name}{method} = $m;
3162 $overridenMethods->{$name}{class} = $classNode;
3163 } elsif ( $m->{ReturnType} eq '~' ) {
3164 if ( ! exists $classNode->{Pure} ) {
3165 $overridenMethods->{~$startNode->{astNodeName}}{method} = $m;
3166 $overridenMethods->{~$startNode->{astNodeName}}{class} = $classNode;
3168 } elsif ( $m->{Access} =~ /private/ ) {
3169 if ( defined $overridenMethods->{$signature} ) { # remove previously defined
3170 delete $overridenMethods->{$signature};
3172 # else, nothing, just ignore private virtual method
3174 my @args = @{ $m->{ParamList} };
3175 my $last = $m->{FirstDefaultParam};
3176 $last = scalar @args unless defined $last;
3177 my $iterationCount = scalar(@args) - $last;
3178 while($iterationCount >= 0) {
3179 my $signature = methodSignature( $m, $#args );
3181 my $propertyName = $m->{astNodeName};
3182 if ( @{$m->{ParamList}} == 1 && $propertyName =~ /^set(.)(.*)/ ) {
3183 $propertyName = "Q_PROPERTY_
" . lc($1) . $2;
3184 my $item = kdocAstUtil::findRef( $classNode, $propertyName );
3185 if ( defined $item && $item->{NodeType} eq 'property' ) {
3186 # If there is a property with the same name, don't bother
3192 if ($signature ne "") {
3193 $overridenMethods->{$signature}{method} = $m;
3194 $overridenMethods->{$signature}{class} = $classNode;
3207 # Known typedef? If so, apply it.
3211 # Parse 'const' in front of it, and '*' or '&' after it
3212 my $prefix = $type =~ s/^const\s+// ? 'const ' : '';
3213 my $suffix = $type =~ s/\s*([\&\*]+)$// ? $1 : '';
3215 if (exists $typedeflist{$type}) {
3216 return $prefix.$typedeflist{$type}.$suffix;
3218 return $prefix.$type.$suffix;
3221 # Register type ($1) into %allTypes if not already there
3222 sub registerType($$) {
3224 #print "registerType
: $type\n" if ($debug);
3226 $type =~ s/\s+const$//; # for 'char* const'
3227 $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'
3229 return if ( $type eq 'void' or $type eq '' or $type eq '~' );
3230 die if ( $type eq '...' ); # ouch
3232 # Let's register the real type, not its known equivalent
3233 #$type = applyTypeDef($type);
3235 # Enum _value_ -> get corresponding type
3236 if (exists $enumValueToType{$type}) {
3237 $type = $enumValueToType{$type};
3240 # Already in allTypes
3241 if(exists $allTypes{$type}) {
3245 die if $type eq 'QTextEdit::UndoRedoInfo::Type';
3248 my $realType = $type;
3250 # Look for references (&) and pointers (* or **) - this will not handle *& correctly.
3251 # We do this parsing here because both the type list and iterproto need it
3252 if($realType =~ s/&$//) {
3253 $allTypes{$type}{typeFlags} = 'Smoke::tf_ref';
3255 elsif($realType ne 'void*' && $realType =~ s/\*$//) {
3256 $allTypes{$type}{typeFlags} = 'Smoke::tf_ptr';
3259 $allTypes{$type}{typeFlags} = 'Smoke::tf_stack';
3262 if ( $realType =~ s/^const\s+// ) { # Remove 'const'
3263 $allTypes{$type}{typeFlags} .= ' | Smoke::tf_const';
3266 # Apply typedefs, and store the resulting type.
3267 # For instance, if $type was Q_UINT16&, realType will be ushort
3268 $allTypes{$type}{realType} = applyTypeDef( $realType );
3270 # In the first phase we only create entries into allTypes.
3271 # The values (indexes) are calculated afterwards, once the list is full.
3272 $allTypes{$type}{index} = -1;
3273 #print STDERR "Register
$type. Realtype
: $realType\n" if($debug);
3276 # Get type from %allTypes
3277 # This returns a hash with {index}, {isEnum}, {typeFlags}, {realType}
3278 # (and {typeId} after the types array is written by writeSmokeDataFile)
3279 sub findTypeEntry($) {
3282 $type =~ s/\s+const$//; # for 'char* const'
3283 $type =~ s/\s+const\s*\*$/\*/; # for 'char* const*'
3285 return undef if ( $type =~ '~' or $type eq 'void' or $type eq '' );
3287 # Enum _value_ -> get corresponding type
3288 if (exists $enumValueToType{$type}) {
3289 $type = $enumValueToType{$type};
3292 if ( ! defined $allTypes{$type} ) {
3293 print("type
not known
: $type\n");
3297 # die "type
not known
: $type" unless defined $allTypes{$type};
3298 return $allTypes{ $type };
3301 # List of all csharp super-classes for a given class, via single inheritance.
3302 # Excluding any which are mapped onto interfaces to avoid multiple inheritance.
3303 sub direct_superclass_list($)
3305 my $classNode = shift;
3307 my $has_ancestor = 0;
3308 my $direct_ancestor = undef;
3311 Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
3312 ( $direct_ancestor, $name ) = @_;
3313 if ($name =~ /QMemArray|QSqlFieldInfoList/) {
3314 # Template classes, give up for now..
3316 } elsif (!defined $interfacemap{$name}) {
3317 push @super, $direct_ancestor;
3318 push @super, direct_superclass_list( $direct_ancestor );
3323 if (! $has_ancestor and defined $direct_ancestor) {
3324 push @super, $direct_ancestor;
3325 push @super, direct_superclass_list( $direct_ancestor );
3331 # List of all super-classes for a given class
3332 sub superclass_list($)
3334 my $classNode = shift;
3336 Iter::Ancestors( $classNode, $rootnode, undef, undef, sub {
3338 push @super, superclass_list( @_[0] );
3345 my $classNode = shift;
3346 my $className = shift;
3348 if ($classNode->{astNodeName} eq $className) {
3352 my @superclasses = superclass_list($classNode);
3353 foreach my $ancestor (@superclasses) {
3354 if ($ancestor->{astNodeName} eq $className) {
3362 # Store the {case} dict in the class Node (method signature -> index in the "case
" switch)
3363 # This also determines which methods should NOT be in the switch, and sets {SkipFromSwitch} for them
3364 sub prepareCaseDict($) {
3366 my $classNode = shift;
3367 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3368 $classNode->AddProp("case
", {});
3369 my $methodNumber = 0;
3371 # First look at all enums for this class
3372 Iter::MembersByType ( $classNode, undef,
3373 sub { my ($classNode, $m ) = @_;
3375 next unless $m->{NodeType} eq 'enum';
3376 foreach my $val ( @{$m->{ParamList}} ) {
3377 my $fullEnumName = "$className\
::".$val->{ArgName};
3378 print STDERR "Enum
: $fullEnumName -> case
$methodNumber\n" if ($debug);
3379 $classNode->{case}{$fullEnumName} = $methodNumber;
3380 $enumValueToType{$fullEnumName} = "$className\
::$m->{astNodeName
}";
3385 # Check for static vars
3386 Iter::MembersByType ( $classNode, undef,
3387 sub { my ($classNode, $m ) = @_;
3389 next unless $m->{NodeType} eq 'var';
3390 my $name = "$className\
::".$m->{astNodeName};
3391 print STDERR "Var
: $name -> case
$methodNumber\n" if ($debug);
3392 $classNode->{case}{$name} = $methodNumber;
3398 # Now look at all methods for this class
3399 Iter::MembersByType ( $classNode, undef,
3400 sub { my ($classNode, $m ) = @_;
3402 next unless $m->{NodeType} eq 'method';
3403 my $name = $m->{astNodeName};
3404 my $isConstructor = ($name eq $classNode->{astNodeName} );
3405 if ($isConstructor and ($m->{ReturnType} eq '~')) # destructor
3407 # Remember whether we'll generate a switch entry for the destructor
3408 $m->{SkipFromSwitch} = 1 unless ($classNode->{CanBeInstanciated} and $classNode->{HasPublicDestructor});
3412 # Don't generate bindings for protected methods (incl. signals) if
3413 # we're not deriving from the C++ class. Only take public and public_slots
3414 my $ok = ( $classNode->{BindingDerives} or $m->{Access} =~ /public/ ) ? 1 : 0;
3416 # Don't generate bindings for pure virtuals - we can't call them ;)
3417 $ok = 0 if ( $ok && $m->{Flags} =~ "p
" );
3419 # Bugfix for Qt-3.0.4: those methods are NOT implemented (report sent).
3420 $ok = 0 if ( $ok && $className eq 'QLineEdit' && ( $name eq 'setPasswordChar' || $name eq 'passwordChar' ) );
3421 $ok = 0 if ( $ok && $className eq 'QWidgetItem' && $name eq 'widgetSizeHint' );
3425 #print STDERR "Skipping
$className\
::$name\n" if ($debug);
3426 $m->{SkipFromSwitch} = 1;
3430 my @args = @{ $m->{ParamList} };
3431 my $last = $m->{FirstDefaultParam};
3432 $last = scalar @args unless defined $last;
3433 my $iterationCount = scalar(@args) - $last;
3434 while($iterationCount >= 0) {
3435 my $sig = methodSignature( $m, $#args );
3436 $classNode->{case}{$sig} = $methodNumber;
3437 #print STDERR "prepareCaseDict
: registered case number
$methodNumber for $sig in $className()\n" if ($debug);
3444 # Add the destructor, at the end
3445 if ($classNode->{CanBeInstanciated} and $classNode->{HasPublicDestructor}) {
3446 $classNode->{case}{"~$className()"} = $methodNumber;
3447 # workaround for ~Sub::Class() being seen as Sub::~Class()
3448 $classNode->{case}{"~$classNode->{astNodeName
}()"} = $methodNumber;
3449 #print STDERR "prepareCaseDict
: registered case number
$methodNumber for ~$className()\n" if ($debug);
3453 sub writeSmokeDataFile($) {
3454 my $rootnode = shift;
3456 # Make list of classes
3457 my %allImports; # list of all header files for all classes
3459 push @classlist, ""; # Prepend empty item for "no class"
3461 Iter::LocalCompounds( $rootnode, sub {
3462 my $classNode = $_[0];
3463 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3465 return if $classNode->{NodeType} eq 'namespace';
3467 push @classlist, $className;
3468 $enumclasslist{$className}++ if keys %{$classNode->{enumerations}};
3469 $classNode->{ClassIndex} = $#classlist;
3470 addImportForClass( $classNode, \%allImports, undef );
3473 my %classidx = do { my $i = 0; map { $_ => $i++ } @classlist };
3475 my $file = "$outputdir/smokedata
.cpp
";
3476 # open OUT, ">$file" or die "Couldn
't create $file\n";
3478 # foreach my $incl (sort{
3479 # return 1 if $a=~/qmotif/; # move qmotif* at bottom (they include dirty X11 headers)
3480 # return -1 if $b=~/qmotif/;
3481 # return -1 if substr($a,0,1) eq 'q
' and substr($b,0,1) ne 'q
'; # move Qt headers on top
3482 # return 1 if substr($a,0,1) ne 'q
' and substr($b,0,1) eq 'q
';
3484 # } keys %allIncludes) {
3485 # die if $imp eq '';
3486 # print OUT "import $imp;\n";
3491 print STDERR "Writing ${libname}_cast function\n" if ($debug);
3493 # Prepare descendants information for each class
3494 my %descendants; # classname -> list of descendant nodes
3495 Iter::LocalCompounds( $rootnode, sub {
3496 my $classNode = shift;
3497 # Get _all_ superclasses (up any number of levels)
3498 # and store that $classNode is a descendant of $s
3499 my @super = superclass_list($classNode);
3500 for my $s (@super) {
3501 my $superClassName = join( "::", kdocAstUtil::heritage($s) );
3502 Ast::AddPropList( \%descendants, $superClassName, $classNode );
3506 # Iterate over all classes, to write the xtypecast function
3507 Iter::LocalCompounds( $rootnode, sub {
3508 my $classNode = shift;
3509 my $className = join( "::", kdocAstUtil::heritage($classNode) );
3510 # @super will contain superclasses, the class itself, and all descendants
3511 my @super = superclass_list($classNode);
3512 push @super, $classNode;
3513 if ( defined $descendants{$className} ) {
3514 push @super, @{$descendants{$className}};
3516 my $cur = $classidx{$className};
3518 return if $classNode->{NodeType} eq 'namespace
';
3520 # print OUT " case $cur:\t//$className\n";
3521 # print OUT "\tswitch(to) {\n";
3524 # for my $s (@super) {
3525 # my $superClassName = join( "::", kdocAstUtil::heritage($s) );
3526 # next if !defined $classidx{$superClassName}; # inherits from unknown class, see below
3527 # next if $classidx{$superClassName} == $cur; # shouldn't happen
in Qt
3528 # next if $s->kdocAstUtil::inheritsAsVirtual($classNode); # can't cast from a virtual base class
3529 # $cur = $classidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
3530 # next if $casevalues{$cur}; # ..so skip any duplicate parents
3531 # print OUT "\t case $cur: return (void*)($superClassName*)($className*)xptr;\n";
3532 # $casevalues{$cur} = 1;
3534 # print OUT "\t default: return xptr;\n";
3535 # print OUT "\t}\n";
3537 # print OUT " default: return xptr;\n";
3539 # print OUT "}\n\n";
3542 # Write inheritance array
3543 # Imagine you have "Class : public super1, super2"
3544 # The inheritlist array will get 3 new items: super1, super2, 0
3545 my %inheritfinder; # key = (super1, super2) -> data = (index in @inheritlist). This one allows reuse.
3546 my %classinherit; # we store that index in %classinherit{className}
3547 # We don't actually need to store inheritlist in memory, we write it
3548 # directly to the file. We only need to remember its current size.
3549 my $inheritlistsize = 1;
3551 # print OUT "// Group of class IDs (0 separated) used as super class lists.\n";
3552 # print OUT "// Classes with super classes have an index into this array.\n";
3553 # print OUT "static short ${libname}_inheritanceList[] = {\n";
3554 # print OUT "\t0,\t// 0: (no super class)\n";
3555 Iter
::LocalCompounds
( $rootnode, sub {
3556 my $classNode = shift;
3557 my $className = join( "__", kdocAstUtil
::heritage
($classNode) );
3559 return if $classNode->{NodeType
} eq 'namespace';
3561 print STDERR
"inheritanceList: looking at $className\n" if ($debug);
3563 # Make list of direct ancestors
3565 Iter
::Ancestors
( $classNode, $rootnode, undef, undef, sub {
3566 my $superClassName = join( "::", kdocAstUtil
::heritage
($_[0]) );
3567 push @super, $superClassName;
3569 # Turn that into a list of class indexes
3571 foreach my $superClass( @super ) {
3572 if (defined $classidx{$superClass}) {
3573 $key .= ', ' if ( length $key > 0 );
3574 $key .= $classidx{$superClass};
3578 if ( !defined $inheritfinder{$key} ) {
3580 my $index = $inheritlistsize; # Index of first entry (for this group) in inheritlist
3581 foreach my $superClass( @super ) {
3582 if (defined $classidx{$superClass}) {
3583 print OUT
"$classidx{$superClass}, ";
3588 my $comment = join( ", ", @super );
3589 print OUT
"0,\t// $index: $comment\n";
3590 $inheritfinder{$key} = $index;
3592 $classinherit{$className} = $inheritfinder{$key};
3593 } else { # No superclass
3594 $classinherit{$className} = 0;
3597 # print OUT "};\n\n";
3600 # print OUT "// These are the xenum functions for manipulating enum pointers\n";
3601 for my $className (keys %enumclasslist) {
3604 # print OUT "void xenum_$c\(Smoke::EnumOperation, Smoke::Index, void*&, long&);\n";
3607 # print OUT "// Those are the xcall functions defined in each x_*.cpp file, for dispatching method calls\n";
3609 for my $className (@classlist) {
3614 my $c = $className; # make a copy
3616 # print OUT "void xcall_$c\(Smoke::Index, void*, Smoke::Stack);\n";
3620 # Write class list afterwards because it needs offsets to the inheritance array.
3621 # print OUT "// List of all classes\n";
3622 # print OUT "// Name, index into inheritanceList, method dispatcher, enum dispatcher, class flags\n";
3623 # print OUT "static Smoke::Class ${libname}_classes[] = {\n";
3625 Iter
::LocalCompounds
( $rootnode, sub {
3626 my $classNode = shift;
3627 my $className = join( "__", kdocAstUtil
::heritage
($classNode) );
3629 return if $classNode->{NodeType
} eq 'namespace';
3633 print OUT
"\t{ 0L, 0, 0, 0, 0 }, \t// 0 (no class)\n";
3637 my $xcallFunc = "xcall_$c";
3638 my $xenumFunc = "0";
3639 $xenumFunc = "xenum_$c" if exists $enumclasslist{$className};
3640 # %classinherit needs Foo__Bar, not Foo::Bar?
3641 die "problem with $className" unless defined $classinherit{$c};
3643 my $xClassFlags = 0;
3644 $xClassFlags .= "|Smoke::cf_constructor" if $classNode->{CanBeInstanciated
}; # correct?
3645 $xClassFlags .= "|Smoke::cf_deepcopy" if $classNode->{CanBeCopied
}; # HasCopyConstructor would be wrong (when it's private)
3646 $xClassFlags .= "|Smoke::cf_virtual" if hasVirtualDestructor
($classNode, $classNode) == 1;
3647 # $xClassFlags .= "|Smoke::cf_undefined" if ...;
3648 $xClassFlags =~ s/0\|//; # beautify
3649 # print OUT "\t{ \"$className\", $classinherit{$c}, $xcallFunc, $xenumFunc, $xClassFlags }, \t//$classidx{$className}\n";
3651 # print OUT "};\n\n";
3654 # print OUT "// List of all types needed by the methods (arguments and return values)\n";
3655 # print OUT "// Name, class ID if arg is a class, and TypeId\n";
3656 # print OUT "static Smoke::Type ${libname}_types[] = {\n";
3658 $allTypes{''}{index} = 0; # We need an "item 0"
3659 for my $type (sort keys %allTypes) {
3660 $allTypes{$type}{index} = $typeCount; # Register proper index in allTypes
3661 if ( $typeCount == 0 ) {
3662 # print OUT "\t{ 0, 0, 0 },\t//0 (no type)\n";
3666 my $isEnum = $allTypes{$type}{isEnum
};
3668 my $typeFlags = $allTypes{$type}{typeFlags
};
3669 my $realType = $allTypes{$type}{realType
};
3670 die "$type" if !defined $typeFlags;
3671 # die "$realType" if $realType =~ /\(/;
3672 # First write the name
3673 # print OUT "\t{ \"$type\", ";
3674 # Then write the classId (and find out the typeid at the same time)
3675 if(exists $classidx{$realType}) { # this one first, we want t_class for QBlah*
3676 $typeId = 't_class';
3677 # print OUT "$classidx{$realType}, ";
3679 elsif($type =~ /&$/ || $type =~ /\*$/) {
3680 $typeId = 't_voidp';
3681 # print OUT "0, "; # no classId
3683 elsif($isEnum || $allTypes{$realType}{isEnum
}) {
3685 if($realType =~ /(.*)::/) {
3688 # print OUT "$classidx{$c}, ";
3690 # print OUT "0 /* unknown class $c */, ";
3693 # print OUT "0 /* unknown $realType */, "; # no classId
3697 $typeId = $typeunion{$realType};
3698 if (defined $typeId) {
3699 $typeId =~ s/s_/t_/; # from s_short to t_short for instance
3702 # Not a known class - ouch, this happens quite a lot
3703 # (private classes, typedefs, template-based types, etc)
3704 if ( $skippedClasses{$realType} ) {
3705 # print STDERR "$realType has been skipped, using t_voidp for it\n";
3707 unless( $realType =~ /</ ) { # Don't warn for template stuff...
3708 print STDERR
"$realType isn't a known type (type=$type)\n";
3711 $typeId = 't_voidp'; # Unknown -> map to a void *
3713 # print OUT "0, "; # no classId
3715 # Then write the flags
3716 die "$type" if !defined $typeId;
3717 # print OUT "Smoke::$typeId | $typeFlags },";
3718 # print OUT "\t//$typeCount\n";
3720 # Remember it for coerce_type
3721 $allTypes{$type}{typeId
} = $typeId;
3723 # print OUT "};\n\n";
3726 my %arglist; # registers the needs for argumentList (groups of type ids)
3728 # Look for all methods and all enums, in all classes
3729 # And fill in methods and arglist. This loop writes nothing to OUT.
3730 Iter
::LocalCompounds
( $rootnode, sub {
3731 my $classNode = shift;
3732 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
3733 print STDERR
"writeSmokeDataFile: arglist: looking at $className\n" if ($debug);
3735 Iter
::MembersByType
( $classNode, undef,
3736 sub { my ($classNode, $m ) = @_;
3738 my $methName = $m->{astNodeName
};
3739 # For destructors, get a proper signature that includes the '~'
3740 if ( $m->{ReturnType
} eq '~' )
3742 $methName = '~' . $methName ;
3743 # Let's even store that change, otherwise we have to do it many times
3744 $m->{astNodeName
} = $methName;
3747 if( $m->{NodeType
} eq "enum" ) {
3749 foreach my $enum ( @
{$m->{ParamList
}} ) {
3750 my $enumName = $enum->{ArgName
};
3751 $methods{$enumName}++;
3754 } elsif ( $m->{NodeType
} eq 'var' ) {
3756 $methods{$m->{astNodeName
}}++;
3758 } elsif( $m->{NodeType
} eq "method" ) {
3760 $methods{$methName}++;
3762 makeprotos
(\
%classidx, $m, \
@protos);
3764 #print "made @protos from $className $methName $m->{Signature})\n" if ($debug);
3765 for my $p (@protos) {
3768 $argcnt = length($1) if $p =~ /([\$\#\?]+)/;
3769 my $sig = methodSignature
($m, $argcnt-1);
3770 # Store in a class hash named "proto", a proto+signature => method association
3771 $classNode->{proto
}{$p}{$sig} = $m;
3772 #$classNode->{signature}{$sig} = $p;
3773 # There's probably a way to do this better, but this is the fastest way
3774 # to get the old code going: store classname into method
3775 $m->{class} = $className;
3778 my $firstDefaultParam = $m->{FirstDefaultParam
};
3779 $firstDefaultParam = scalar(@
{ $m->{ParamList
} }) unless defined $firstDefaultParam;
3782 for(my $i = 0; $i < @
{ $m->{ParamList
} }; $i++) {
3783 $args .= ', ' if $i;
3784 $argNames .= ', ' if $i;
3785 my $argType = $m->{ParamList
}[$i]{ArgType
};
3786 my $typeEntry = findTypeEntry
( $argType );
3787 $args .= defined $typeEntry ?
$typeEntry->{index} : 0;
3788 $argNames .= $argType;
3790 if($i >= ($firstDefaultParam - 1)) {
3791 #print "arglist entry: $args\n";
3792 $arglist{$args} = $argNames;
3796 # create an entry for e.g. "arg0,arg1,arg2" where argN is index in allTypes of type for argN
3797 # The value, $argNames, is temporarily stored, to be written out as comment
3798 # It gets replaced with the index in the next loop.
3799 #print "arglist entry : $args\n";
3800 $arglist{$args} = $argNames;
3809 # Print arguments array
3810 # print OUT "static Smoke::Index ${libname}_argumentList[] = {\n";
3811 my $argListCount = 0;
3812 for my $args (sort keys %arglist) {
3813 my @dunnohowtoavoidthat = split(',',$args);
3814 my $numTypes = $#dunnohowtoavoidthat;
3816 # print OUT "\t0,\t//0 (void)\n";
3818 # This is a nice trick : args can be written in one go ;)
3819 # print OUT "\t$args, 0,\t//$argListCount $arglist{$args} \n";
3821 $arglist{$args} = $argListCount; # Register proper index in argList
3822 $argListCount += $numTypes + 2; # Move forward by as much as we wrote out
3824 # print OUT "};\n\n";
3827 my @methodlist = sort keys %methods;
3828 my %methodidx = do { my $i = 0; map { $_ => $i++ } @methodlist };
3830 # print OUT "// Raw list of all methods, using munged names\n";
3831 # print OUT "static const char *${libname}_methodNames[] = {\n";
3832 my $methodNameCount = $#methodlist;
3833 for my $m (@methodlist) {
3834 # print OUT qq( "$m",\t//$methodidx{$m}\n);
3836 # print OUT "};\n\n";
3838 # print OUT "// (classId, name (index in methodNames), argumentList index, number of args, method flags, return type (index in types), xcall() index)\n";
3839 # print OUT "static Smoke::Method ${libname}_methods[] = {\n";
3842 my $methodCount = 0;
3843 # Look at all classes and all enums again
3844 Iter
::LocalCompounds
( $rootnode, sub {
3845 my $classNode = shift;
3846 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
3847 return if $classNode->{NodeType
} eq 'namespace';
3849 my $classIndex = $classidx{$className};
3850 print STDERR
"writeSmokeDataFile: methods: looking at $className\n" if ($debug);
3852 Iter
::MembersByType
( $classNode, undef,
3853 sub { my ($classNode, $m ) = @_;
3855 if( $m->{NodeType
} eq "enum" ) {
3857 foreach my $enum ( @
{$m->{ParamList
}} ) {
3858 my $enumName = $enum->{ArgName
};
3859 my $fullEnumName = "$className\::$enumName";
3860 my $sig = "$className\::$enumName\()";
3861 my $xmethIndex = $methodidx{$enumName};
3862 die "'Method index' for enum $sig not found" unless defined $xmethIndex;
3863 my $typeId = findTypeEntry
( $fullEnumName )->{index};
3864 die "enum has no {case} value in $className: $fullEnumName" unless defined $classNode->{case
}{$fullEnumName};
3865 # print OUT "\t{$classIndex, $xmethIndex, 0, 0, Smoke::mf_static, $typeId, $classNode->{case}{$fullEnumName}},\t//$methodCount $fullEnumName (enum)\n";
3866 $allMethods{$sig} = $methodCount;
3867 print STDERR
"Added entry for " . $sig . " into \$allMethods\n" if ($debug);
3868 $methods[$methodCount] = {
3870 methIndex
=> $xmethIndex,
3874 idx
=> $classNode->{case
}{$fullEnumName}
3879 } elsif( $m->{NodeType
} eq 'var' ) {
3881 my $name = $m->{astNodeName
};
3882 my $fullName = "$className\::$name";
3883 my $sig = "$fullName\()";
3884 my $xmethIndex = $methodidx{$name};
3885 die "'Method index' for var $sig not found" unless defined $xmethIndex;
3886 my $varType = $m->{Type
};
3887 $varType =~ s/static\s//;
3888 $varType =~ s/const\s+(.*)\s*&/$1/;
3889 $varType =~ s/\s*$//;
3890 my $typeId = findTypeEntry
( $varType )->{index};
3891 die "var has no {case} value in $className: $fullName" unless defined $classNode->{case
}{$fullName};
3892 # print OUT "\t{$classIndex, $xmethIndex, 0, 0, Smoke::mf_static, $typeId, $classNode->{case}{$fullName}},\t//$methodCount $fullName (static var)\n";
3893 $allMethods{$sig} = $methodCount;
3894 print STDERR
"Added entry for " . $sig . " into \$allMethods\n" if ($debug);
3895 $methods[$methodCount] = {
3897 methIndex
=> $xmethIndex,
3901 idx
=> $classNode->{case
}{$fullName}
3906 } elsif( $m->{NodeType
} eq "method" ) {
3908 # We generate a method entry only if the method is in the switch() code
3909 # BUT: for pure virtuals, they need to have a method entry, even though they
3910 # do NOT have a switch code.
3911 return if ( $m->{SkipFromSwitch
} && $m->{Flags
} !~ "p" );
3913 # No switch code for destructors if we didn't derive from the class (e.g. it has private ctors only)
3914 return if ( $m->{ReturnType
} eq '~' && ! ( $classNode->{BindingDerives
} and $classNode->{HasPublicDestructor
}) );
3916 # Is this sorting really important?
3917 #for my $m (sort {$a->{name} cmp $b->{name}} @{ $self->{$c}{method} }) {
3919 my $methName = $m->{astNodeName
};
3920 my $def = $m->{FirstDefaultParam
};
3921 $def = scalar(@
{ $m->{ParamList
} }) unless defined $def;
3922 my $last = scalar(@
{ $m->{ParamList
} }) - 1;
3923 #print STDERR "writeSmokeDataFile: methods: generating for method $methName, def=$def last=$last\n" if ($debug);
3925 while($last >= ($def-1)) {
3927 my $args = [ @
{ $m->{ParamList
} }[0..$last] ];
3928 my $sig = methodSignature
($m, $last);
3929 #my $methodSig = $classNode->{signature}{$sig}; # Munged signature
3930 #print STDERR "writeSmokeDataFile: methods: sig=$className\::$sig methodSig=$methodSig\n" if ($debug);
3931 #my $methodIndex = $methodidx{$methodSig};
3932 #die "$methodSig" if !defined $methodIndex;
3934 my $methodIndex = $methodidx{$methName};
3935 die "$methName" if !defined $methodIndex;
3936 my $case = $classNode->{case
}{$sig};
3937 my $typeEntry = findTypeEntry
( $m->{ReturnType
} );
3938 my $retTypeIndex = defined $typeEntry ?
$typeEntry->{index} : 0;
3942 for my $arg (@
$args) {
3944 my $typeEntry = findTypeEntry
( $arg->{ArgType
} );
3945 $t .= defined $typeEntry ?
$typeEntry->{index} : 0;
3947 my $arglist = $t eq '' ?
0 : $arglist{$t};
3948 die "arglist for $t not found" unless defined $arglist;
3949 if ( $m->{Flags
} =~ "p" ) {
3950 # Pure virtuals don't have a {case} number, that's normal
3951 die if defined $case;
3952 $case = -1; # This remains -1, not 0 !
3955 # die "$className\::$methName has no case number for sig=$sig" unless defined $case;
3957 my $argcnt = $last + 1;
3958 my $methodFlags = '0';
3959 $methodFlags .= "|Smoke::mf_static" if $m->{Flags
} =~ "s";
3960 $methodFlags .= "|Smoke::mf_const" if $m->{Flags
} =~ "c"; # useful?? probably not
3961 $methodFlags =~ s/0\|//; # beautify
3963 # print OUT "\t{$classIndex, $methodIndex, $arglist, $argcnt, $methodFlags, $retTypeIndex, $case},\t//$methodCount $className\::$sig";
3964 # print OUT " [pure virtual]" if ( $m->{Flags} =~ "p" ); # explain why $case = -1 ;)
3967 $allMethods{$className . "::" . $sig} = $methodCount;
3968 $methods[$methodCount] = {
3970 methIndex
=> $methodIndex,
3973 retTypeIndex
=> $retTypeIndex,
3982 # print OUT "};\n\n";
3985 Iter
::LocalCompounds
( $rootnode, sub {
3986 my $classNode = shift;
3987 my $className = join( "::", kdocAstUtil
::heritage
($classNode) );
3989 return if $classNode->{NodeType
} eq 'namespace';
3991 my $classIndex = $classidx{$className};
3992 print STDERR
"writeSmokeDataFile: protos: looking at $className\n" if ($debug);
3994 Iter
::MembersByType
( $classNode, undef,
3995 sub { my ($classNode, $m ) = @_;
3997 if( $m->{NodeType
} eq "enum" ) {
3998 foreach my $enum ( @
{$m->{ParamList
}} ) {
3999 my $enumName = $enum->{ArgName
};
4000 my $sig = "$className\::$enumName\()";
4001 my $xmeth = $allMethods{$sig};
4002 die "'Method' for enum $sig not found" unless defined $xmeth;
4003 my $xmethIndex = $methodidx{$enumName};
4004 die "'Method index' for enum $enumName not found" unless defined $xmethIndex;
4006 methIndex
=> $xmethIndex,
4017 } elsif( $m->{NodeType
} eq 'var' ) {
4019 my $name = $m->{astNodeName
};
4020 my $fullName = "$className\::$name";
4021 my $sig = "$fullName\()";
4022 my $xmeth = $allMethods{$sig};
4023 die "'Method' for var $sig not found" unless defined $xmeth;
4024 my $xmethIndex = $methodidx{$name};
4025 die "'Method index' for var $name not found" unless defined $xmethIndex;
4027 methIndex
=> $xmethIndex,
4040 for my $p (keys %{ $classNode->{proto
} }) {
4041 # For each prototype
4042 my $scratch = { %{ $classNode->{proto
}{$p} } }; # sig->method association
4043 # first, grab all the superclass voodoo
4044 for my $supNode (superclass_list
($classNode)) {
4045 my $i = $supNode->{proto
}{$p};
4047 for my $k (keys %$i) {
4048 $scratch->{$k} = $i->{$k} unless exists $scratch->{$k};
4052 # Ok, now we have a full list
4053 #if(scalar keys %$scratch > 1) {
4054 #print STDERR "Overload: $p (@{[keys %$scratch]})\n" if ($debug);
4056 my $xmethIndex = $methodidx{$p};
4057 my $classIndex = $classidx{$className};
4058 for my $sig (keys %$scratch) {
4059 #my $xsig = $scratch->{$sig}{class} . "::" . $sig;
4060 my $xsig = $className . "::" . $sig;
4061 $scratch->{$sig}{sig
} = $xsig;
4062 delete $scratch->{$sig}
4063 if $scratch->{$sig}{Flags
} =~ "p" # pure virtual
4064 or not exists $allMethods{$xsig};
4067 methIndex
=> $xmethIndex,
4070 } if scalar keys %$scratch;
4074 my @protolist = sort { $a->{c
} <=> $b->{c
} || $a->{methIndex
} <=> $b->{methIndex
} } @protos;
4075 #for my $abc (@protos) {
4076 #print "$abc->{methIndex}.$abc->{c}\n";
4079 print STDERR
"Writing methodmap table\n" if ($debug);
4081 # print OUT "// Class ID, munged name ID (index into methodNames), method def (see methods) if >0 or number of overloads if <0\n";
4082 my $methodMapCount = 1;
4083 # print OUT "static Smoke::MethodMap ${libname}_methodMaps[] = {\n";
4084 # print OUT "\t{ 0, 0, 0 },\t//0 (no method)\n";
4085 for my $cur (@protolist) {
4086 if(scalar keys %{ $cur->{over
} } > 1) {
4087 # print OUT "\t{$cur->{c}, $cur->{methIndex}, -@{[1+scalar @resolve]}},\t//$methodMapCount $classlist[$cur->{c}]\::$methodlist[$cur->{methIndex}]\n";
4089 for my $k (keys %{ $cur->{over
} }) {
4090 my $p = $cur->{over
}{$k};
4091 my $xsig = $p->{class} ?
"$p->{class}\::$k" : $p->{sig
};
4092 push @resolve, { k
=> $k, p
=> $p, cur
=> $cur, id
=> $allMethods{$xsig} };
4096 for my $k (keys %{ $cur->{over
} }) {
4097 my $p = $cur->{over
}{$k};
4098 my $xsig = $p->{class} ?
"$p->{class}\::$k" : $p->{sig
};
4099 # print OUT "\t{$cur->{c}, $cur->{methIndex}, $allMethods{$xsig}},\t//$methodMapCount $classlist[$cur->{c}]\::$methodlist[$cur->{methIndex}]\n";
4104 # print OUT "};\n\n";
4107 print STDERR
"Writing ambiguousMethodList\n" if ($debug);
4108 # print OUT "static Smoke::Index ${libname}_ambiguousMethodList[] = {\n";
4109 # print OUT " 0,\n";
4110 for my $r (@resolve) {
4112 # print OUT " 0,\n";
4115 my $xsig = $r->{p
}{class} ?
"$r->{p}{class}\::$r->{k}" : $r->{p
}{sig
};
4116 die "ambiguousMethodList: no method found for $xsig\n" if !defined $allMethods{$xsig};
4117 # print OUT " $allMethods{$xsig}, // $xsig\n";
4119 # print OUT "};\n\n";
4121 # print OUT "extern \"C\" { // needed?\n";
4122 # print OUT " void init_${libname}_Smoke();\n";
4125 # print OUT "Smoke* qt_Smoke = 0L;\n";
4127 # print OUT "// Create the Smoke instance encapsulating all the above.\n";
4128 # print OUT "void init_${libname}_Smoke() {\n";
4129 # print OUT " qt_Smoke = new Smoke(\n";
4130 # print OUT " ${libname}_classes, ".$#classlist.",\n";
4131 # print OUT " ${libname}_methods, $methodCount,\n";
4132 # print OUT " ${libname}_methodMaps, $methodMapCount,\n";
4133 # print OUT " ${libname}_methodNames, $methodNameCount,\n";
4134 # print OUT " ${libname}_types, $typeCount,\n";
4135 # print OUT " ${libname}_inheritanceList,\n";
4136 # print OUT " ${libname}_argumentList,\n";
4137 # print OUT " ${libname}_ambiguousMethodList,\n";
4138 # print OUT " ${libname}_cast );\n";
4142 #print "@{[keys %allMethods ]}\n";
4147 my ( $indent, $text ) = @_;
4149 if ( $indent eq "" || $text eq "" ) {
4153 $text =~ s/\n(.)/\n$indent$1/g;
4154 return $indent . $text;
4157 =head2 printCSharpdocComment
4159 Parameters: docnode filehandle
4161 Converts a kdoc comment to csharpdoc format.
4162 @ref's are converted to <see>'s; @p's and @em's are converted
4167 sub printCSharpdocComment
($$$$)
4169 my( $docnode, $name, $indent, $signalLink ) = @_;
4172 my $returntext = '<remarks>';
4173 foreach $node ( @
{$docnode->{Text
}} ) {
4174 next if $node->{NodeType
} ne "DocText" and $node->{NodeType
} ne "ListItem"
4175 and $node->{NodeType
} ne "Param";
4178 if ($node->{NodeType
} eq "Param") {
4179 if ($node->{Name
} !~ /argc/) {
4180 $line = "<param> name=\"" . $node->{Name
} . "\" " . $node->{astNodeName
} . "</param>";
4183 $line = $node->{astNodeName
};
4185 $line =~ s/argc, ?argv/args/g;
4186 $line =~ s/int argc, ?char ?\* ?argv(\[\])?/string[] args/g;
4187 $line =~ s/int argc, ?char ?\*\* ?argv/string[] args/g;
4188 # if ($node->{NodeType} eq "Param") {
4189 # $line =~ s/(const )?QC?StringList(\s*&)?/string[]/g;
4191 $line =~ s/(const )?QC?StringList(\s*&)?/List<string>/g;
4193 $line =~ s/NodeList/ArrayList/g;
4194 $line =~ s/KTrader::OfferList/ArrayList/g;
4195 $line =~ s/QString::null/null/g;
4196 $line =~ s/(const )?QC?String(\s*&)?/string/g;
4197 $line =~ s/KCmdLineLastOption//g;
4198 $line =~ s/virtual //g;
4199 $line =~ s/~\w+\(\)((\s*{\s*})|;)//g;
4200 $line =~ s/0L/null/g;
4201 $line =~ s/(\([^\)]*\))\s*:\s*\w+\([^\)]*\)/$1/g;
4202 $line =~ s/\(void\)//g;
4203 $line =~ s/const char/string/g;
4204 $line =~ s/const (\w+)\&/$1/g;
4205 $line =~ s/bool/bool/g;
4206 $line =~ s/SLOT\(\s*([^\)]*)\) ?\)/SLOT("$1)")/g;
4207 $line =~ s/SIGNAL\(\s*([^\)]*)\) ?\)/SIGNAL("$1)")/g;
4208 $line =~ s/Q_OBJECT\n//g;
4209 $line =~ s/public\s*(slots)?:\n/public /g;
4210 $line =~ s/([^0-9"]\s*)\*(\s*[^0-9"-])/$1$2/g;
4211 $line =~ s/^(\s*)\*/$1/g;
4212 $line =~ s/\n \*/\n /g;
4213 $line =~ s!\@ref\s+([\w]+)::([\w]+)\s*(\([^\)]*\))(\.)?!<see cref=\"$1#$2\"></see>$4!g;
4214 $line =~ s!\@ref\s+#([\w:]+)(\(\))?!<see cref=\"#$1\"</see>!g;
4215 $line =~ s!\@ref\s+([\w]+)\s*(\([^\)]*\))!<see cref=\"#$1\"></see>!g;
4216 $line =~ s!\@ref\s+([\w]+)::([\w]+)!<see cref=\"$1#$2\"></see>!g;
4217 $line =~ s!\@ref\s+([a-z][\w]+)!<see cref=\"#$1\"></see>!g;
4218 $line =~ s!\@ref\s+([\w]+)!<see cref=\"$1\"></see>!g;
4219 while ($line =~ /\@c\s+([\w#\\\.<>]+)/ ) {
4221 $code =~ s!<!<!g;
4222 $code =~ s!>!>!g;
4224 $line =~ s!\@c\s+([\w#\\\.<>]+)!<code>$code</code>!;
4226 $line =~ s!\@em\s+(\w+)!<b>$1</b>!g;
4227 $line =~ s!\@p\s+([\w\._]*)!<code>$1</code>!g;
4228 $line =~ s!\\paragraph\s+[\w]+\s([\w]+)!<li><b>$1</b></li>!g;
4229 $line =~ s!\\b\s+([\w -]+)\\n!<li><b>$1</b></li>!g;
4230 $line =~ s!\\c\s+([\w\@&\\?;-]+)!<code>$1</code>!g;
4231 $line =~ s!\\p\s+([\w\@]+)!<pre>$1</pre>!g;
4232 $line =~ s!\\li\s+([\w\@]+)!<li>$1</li>!g;
4233 $line =~ s!<b>([\w\t \(\)-]*:?)</b>\\n!<li><b>$1</b></li>!g;
4234 $line =~ s!static_cast<\s*([\w\.]*)\s*>!($1)!g;
4235 # if ($name ne "") {
4236 # $line =~ s/\@link #/\@link $name\#/g;
4239 if ($node->{NodeType
} eq "ListItem") {
4240 $line =~ s/^/\n<li>\n/;
4241 $line =~ s!$!\n</li>!;
4242 # $line =~ s/\n/\n$indent\t/g;
4244 # $line =~ s/^/$indent/;
4245 # $line =~ s/\n/\n$indent/g;
4248 # $line =~ s/\n/\n$indent/g;
4249 $returntext .= $line;
4252 $returntext .= "$signalLink</remarks>";
4254 if ( defined $docnode->{Returns
} ) {
4255 my $text = $docnode->{Returns
};
4256 $text =~ s/QString::null/null/g;
4257 $returntext .= "\t\t<return> $text</return>\n";
4260 if ( defined $docnode->{Author
} ) {
4261 $returntext .= "\t\t<author> " . $docnode->{Author
} . "</author>\n"
4264 if ( defined $docnode->{Version
} ) {
4265 my $versionStr = $docnode->{Version
};
4266 $versionStr =~ s/\$\s*Id:([^\$]*) Exp \$/$1/;
4267 $returntext .= "\t\t<version> $versionStr</version>\n";
4270 if ( defined $docnode->{ClassShort
} ) {
4271 my $shortText = $docnode->{ClassShort
};
4272 $shortText =~ s![\*\n]! !g;
4273 $returntext .= "\t\t<short> $shortText</short>\n";
4276 if ( defined $docnode->{See
} ) {
4277 foreach my $text ( @
{$docnode->{See
}} ) {
4278 next if ($text =~ /QString|^\s*and\s*$|^\s*$|^[^\w]*$/);
4279 $text =~ s/KIO:://g;
4280 $text =~ s/KParts:://g;
4281 while ($text =~ /((::)|(->))(.)/) {
4283 $text =~ s/$1$4/.$temp/;
4286 $text =~ s/^\s*([a-z].*)/$1/g;
4287 $returntext .= "\t\t<see> $text</see>\n";
4291 $returntext =~ s!\\link!<see>!g;
4292 $returntext =~ s!\\endlink!</see>!g;
4293 $returntext =~ s/DOM#([A-Z])/$1/g;
4294 $returntext =~ s/KIO#([A-Z])/$1/g;
4295 $returntext =~ s/KParts#([A-Z])/$1/g;
4296 $returntext =~ s/const\s+(\w+)\s*\&/$1/g;
4297 # $returntext =~ s/QChar/char/g;
4298 $returntext =~ s/QStringList/List<string>/g;
4299 $returntext =~ s/([Aa]) ArrayList/$1n ArrayList/g;
4300 $returntext =~ s/QString/string/g;
4301 $returntext =~ s!\\note!<b>Note:<\b>!g;
4302 $returntext =~ s!\\(code|verbatim)!<pre>!g;
4303 $returntext =~ s!\\(endcode|endverbatim)!</pre>!g;
4304 $returntext =~ s!\\addtogroup\s+[\w]+\s+"([^"\@]+)"\s+\@{!<li><b>$1</b></li>!g;
4305 $returntext =~ s![\\\@]relates\s+([a-z][\w]*)!<see cref=\"$1\"></see>!g;
4306 $returntext =~ s![\\\@]relates\s+(\w+)::(\w+)!<see cref=\"$1.$2\"></see>!g;
4307 $returntext =~ s![\\\@]relates\s+(#?\w+)!<see cref=\"$1\"></see>!g;
4308 $returntext =~ s!\\c\s+([\w\@&\\?";-]+)!<code>$1</code>!g;
4309 $returntext =~ s!\@p\s+([\w\._]*)!<code>$1</code>!g;
4310 $returntext =~ s!\@a\s+([:\w]+)!<b>$1</b>!g;
4311 $returntext =~ s![\@\\]b\s+[:\w]!<b>$1</b>!g;
4312 $returntext =~ s/};/}/g;
4314 while ($returntext =~ /((::)|(->))(.)/) {
4316 $returntext =~ s/$1$4/.$temp/;
4319 $returntext =~ s/\s*$//;
4320 if ($returntext =~ /^<remarks>\s*<\/remarks
>$/) {
4323 $returntext =~ s/\n/\n$indent/g;
4324 $returntext =~ s/^/$indent/;
4325 return $returntext . "\n";