[Kde-bindings] branches/work/kdebindings-smoke2
Arno Rehn
kde at arnorehn.de
Wed Jul 18 00:53:05 UTC 2007
SVN commit 689263 by arnorehn:
* Made some more or less final changes to smoke.h
* Code generation works well, however it could be beautified a bit more.
Looks more like a big hack than proper code.
Generation for the type list could also be improved, it still has too
many redundant types in it.
* The code generation for smoke modules with parents currently relies on
a text file generated together with each module. Use a smoke
introspection tool like the one proposed by Thomas Moenicke instead.
CCMAIL: kde-bindings at kde.org
M +12 -1 ChangeLog
M +3 -2 kalyptus/kalyptus
M +67 -27 kalyptus/kalyptusCxxToSmoke.pm
M +16 -6 smoke/smoke.h
--- branches/work/kdebindings-smoke2/ChangeLog #689262:689263
@@ -1,5 +1,16 @@
-2007-07-14 Arno Rehn <arno at arnorehn.de>
+2007-07-18 Arno Rehn <arno at arnorehn.de>
+ * Made some more or less final changes to smoke.h
+ * Code generation works well, however it could be beautified a bit more.
+ Looks more like a big hack than proper code.
+ Generation for the type list could also be improved, it still has too
+ many redundant types in it.
+ * The code generation for smoke modules with parents currently relies on
+ a text file generated together with each module. Use a smoke
+ introspection tool like the one proposed by Thomas Moenicke instead.
+
+2007-07-17 Arno Rehn <arno at arnorehn.de>
+
* Modified smoke.h to work with split smoke libraries
* Changed the code generation in kalyptus to produce the desired output.
The cast function and the type array need some additional care, they
--- branches/work/kdebindings-smoke2/kalyptus/kalyptus #689262:689263
@@ -23,7 +23,7 @@
use vars qw/ %rootNodes $declNodeType @includes_list %options @formats_wanted $allow_k_dcop_accessors
@includeclasses $includeclasses $skipInternal %defines $defines $match_qt_defines
$libdir $libname $outputdir @libs $parse_global_space $qt_embedded $qt4 $striphpath $doPrivate $readstdin
- $Version $quiet $debug $debuggen $parseonly $currentfile $cSourceNode $exe
+ $Version $quiet $debug $debuggen $parseonly $parentModules $currentfile $cSourceNode $exe
%formats %flagnames @allowed_k_dcop_accesors $allowed_k_dcop_accesors_re $rootNode
@classStack $cNode $globalSpaceClassName
$lastLine $docNode @includes $cpp $defcppcmd $cppcmd $docincluded
@@ -167,7 +167,8 @@
"quiet|q", \$quiet,
"debug|D", \$debug, # debug the parsing
"debuggen", \$debuggen, # debug the file generation
- "parse-only", \$parseonly )
+ "parse-only", \$parseonly,
+ "parent-modules=s", \$parentModules)
|| exit 1;
$| = 1 if $debug or $debuggen;
--- branches/work/kdebindings-smoke2/kalyptus/kalyptusCxxToSmoke.pm #689262:689263
@@ -303,6 +303,7 @@
close DAT;
chop(@lines);
$parentModules{$lines[0]} = $moduleIndex;
+ #$parentModules{$moduleIndex} = $lines[0];
for (my $i = 1; $i <= $#lines; $i++) {
my @splitLine = split(/\t/, $lines[$i]);
if ($splitLine[0] != "0") { # make sure there's no invalid entry
@@ -886,13 +887,19 @@
# Resolve type in full, e.g. for QSessionManager::RestartHint
# (x_QSessionManager doesn't inherit QSessionManager)
$arg->{ArgType} = kalyptusDataDict::resolveType($arg->{ArgType}, $classNode, $rootnode);
- registerType( $arg->{ArgType} );
+
+ # Only add the type if the class using it is not defined in another module.
+ # If the method is virtual, add the type anyway. A class in the current module might reimplement
+ # that method.
+ # TODO: Check if $className is actually an ancestor of any of the classes in this module.
+ # Only add the types of the virtual method if that's the case.
+ registerType( $arg->{ArgType} ) unless (defined($excludeClasses{$className}) && !($m->{Flags} =~ "v"));
$argId++;
}
}
$m->AddProp( "FirstDefaultParam", $firstDefaultParam );
$m->{ReturnType} = kalyptusDataDict::resolveType($m->{ReturnType}, $classNode, $rootnode) if ($m->{ReturnType});
- registerType( $m->{ReturnType} );
+ registerType( $m->{ReturnType} ) unless (defined($excludeClasses{$className}) && !($m->{Flags} =~ "v"));
}
elsif( $m->{NodeType} eq "enum" ) {
my $fullEnumName = $className."::".$m->{astNodeName};
@@ -907,10 +914,10 @@
if $m->{astNodeName} and $m->{Access} ne 'private';
# Define a type for this enum
- registerType( $fullEnumName );
+ registerType( $fullEnumName ) unless (defined $excludeClasses{$className});
# Remember that it's an enum
- findTypeEntry( $fullEnumName )->{isEnum} = 1;
+ findTypeEntry( $fullEnumName )->{isEnum} = 1 unless (defined $excludeClasses{$className});
#print STDERR "$fullEnumName is an enum\n";
}
@@ -939,7 +946,7 @@
print STDERR "var: $m->{astNodeName} '$varType'\n" if ($debug);
# Register the type
- registerType( $varType );
+ registerType( $varType ) unless (defined $excludeClasses{$className});
} else {
$m->{NodeType} = 'deleted';
}
@@ -966,7 +973,7 @@
kdocAstUtil::attachChild( $classNode, $node );
# Register the type
- registerType( $varType );
+ registerType( $varType ) unless (defined $excludeClasses{$className});
} else {
$m->{NodeType} = 'deleted';
}
@@ -993,7 +1000,7 @@
# Hack the return type for constructors, since constructors return an object pointer
$methodNode->AddProp( "ReturnType", $className."*" );
- registerType( $className."*" );
+ registerType( $className."*" ) unless (defined $excludeClasses{$className});
$methodNode->AddProp( "Access", "public" ); # after attachChild
$defaultConstructor = 'public';
$hasPublicProtectedConstructor = 1;
@@ -1053,7 +1060,7 @@
$methodNode->AddProp( "NodeType", "method" );
$methodNode->AddProp( "Flags", "ix" ); # Only for internal use in marshallers
my $argType = "const ".$className."&";
- registerType( $argType );
+ registerType( $argType ) unless (defined $excludeClasses{$className});
$methodNode->AddProp( "Params", $argType );
# The param node
my $node = Ast::New( 1 ); # let's make the arg index the node "name"
@@ -1064,7 +1071,7 @@
# Hack the return type for constructors, since constructors return an object pointer
$methodNode->AddProp( "ReturnType", $className."*" );
- registerType( $className."*" );
+ registerType( $className."*" ) unless (defined $excludeClasses{$className});
$methodNode->AddProp( "Access", "public" ); # after attachChild
}
@@ -1248,7 +1255,8 @@
my $realType = $typeEntry->{realType};
my $unionfield = $typeEntry->{typeId};
- die "$type" unless defined( $unionfield );
+ die "coerce_type: $type" unless defined( $unionfield );
+ return '' unless defined( $unionfield );
$unionfield =~ s/t_/s_/;
$type =~ s/\s+const$//; # for 'char* const'
@@ -1291,6 +1299,7 @@
my $typeEntry = findTypeEntry( $type );
my $unionfield = $typeEntry->{typeId};
die "$type" unless defined( $unionfield );
+ return [] unless defined( $unionfield );
$unionfield =~ s/t_/s_/;
$type =~ s/\s+const$//; # for 'char* const'
@@ -1371,6 +1380,7 @@
return ('', '') if $returnType eq '~'; # skip destructors
my $className = $classNode->{astNodeName};
+ return ('', '') if (defined $excludeClasses{$className});
my $flags = $m->{Flags};
my @argList = @{$m->{ParamList}};
@@ -1402,7 +1412,9 @@
$i = 1;
for my $arg (@argList) {
$methodCode .= "\t";
+# print "warning1 ($className" . '::' . "$m->{astNodeName}): ";
$methodCode .= coerce_type("x[$i]", "x$i", $arg->{ArgType}, 0);
+# print "\n";
$i++;
}
@@ -1492,6 +1504,7 @@
my $name = $m->{astNodeName}; # method name
my @heritage = kdocAstUtil::heritage($classNode);
my $className = join( "::", @heritage );
+ return if (defined $excludeClasses{$className});
my $xClassName = "x_" . join( "__", @heritage );
# Check some method flags: constructor, destructor etc.
@@ -1733,6 +1746,7 @@
my @heritage = kdocAstUtil::heritage($classNode);
my $className = join( "::", @heritage );
+ return ('', '') if (defined $excludeClasses{$className});
my $xClassName = "x_" . join( "__", @heritage );
my $name = $m->{astNodeName};
@@ -1812,6 +1826,7 @@
#my $className = $classNode->{astNodeName};
my $className = join( "::", kdocAstUtil::heritage($classNode) );
+ return ('', '', ()) if (defined $excludeClasses{$className});
my $xClassName = "x_" . join( "__", kdocAstUtil::heritage($classNode) );
my $isGlobalSpace = ($xClassName eq ("x_".$main::globalSpaceClassName));
my $sourcename = $classNode->{Source}->{astNodeName};
@@ -2107,7 +2122,7 @@
$type = $enumValueToType{$type};
}
- die "type not known: $type" unless defined $allTypes{$type};
+ print "type not known: $type" unless defined $allTypes{$type};
return $allTypes{ $type };
}
@@ -2245,6 +2260,7 @@
# Make list of classes
my %allIncludes; # list of all header files for all classes
my @classlist;
+ my @moduleclasslist;
push @classlist, ""; # Prepend empty item for "no class"
my %enumclasslist;
@@ -2253,14 +2269,17 @@
my $className = join( "::", kdocAstUtil::heritage($classNode) );
push @classlist, $className;
+ push @moduleclasslist, $className unless defined($excludeClasses{$className});
$enumclasslist{$className}++ if keys %{$classNode->{enumerations}};
$classNode->{ClassIndex} = $#classlist;
addIncludeForClass( $classNode, \%allIncludes, undef );
} );
my %classidx = do { my $i = 0; map { $_ => $i++ } @classlist };
+ my %moduleclassidx = do { my $i = 0; map { $_ => $i++ } @moduleclasslist };
+
open OUT, ">$outputdir/${libname}_smoke_classlist";
- print OUT "${libname}_Smoke\n";
+ print OUT "${libname}\n";
foreach my $classname (keys(%classidx)) {
print OUT "$classidx{$classname}\t$classname\n";
}
@@ -2290,7 +2309,7 @@
#print OUT "static Smoke* ${libname}_parentModules[] = { 0 };\n\n";
# gcc optimizes this method like crazy. switch() is godly
- print OUT "static void *${libname}_cast(void *xptr, Smoke::Index from, Smoke::Index to) {\n";
+ print OUT "static void *${libname}_cast(void *xptr, Smoke::Index from, Smoke::ParentIndex to) {\n";
print OUT " switch(from) {\n";
print STDERR "Writing ${libname}_cast function\n" if ($debug);
@@ -2319,14 +2338,15 @@
if ( defined $descendants{$className} ) {
push @super, @{$descendants{$className}};
}
- my $cur = $classidx{$className};
+ my $cur = $moduleclassidx{$className};
return if $classNode->{NodeType} eq 'namespace';
print OUT " case $cur:\t//$className\n";
- print OUT "\tswitch(to) {\n";
+ print OUT "\tswitch(to.parent) {\n";
$cur = -1;
my %casevalues;
+ my %moduleCases;
for my $s (@super) {
my $superClassName = join( "::", kdocAstUtil::heritage($s) );
next if !defined $classidx{$superClassName}; # inherits from unknown class, see below
@@ -2335,11 +2355,27 @@
die "problem with $className missing parent"
}
next if $s->kdocAstUtil::inheritsAsVirtual($classNode); # can't cast from a virtual base class
- $cur = $classidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
- next if $casevalues{$cur}; # ..so skip any duplicate parents
- print OUT "\t case $cur: return (void*)($superClassName*)($className*)xptr;\n";
- $casevalues{$cur} = 1;
+
+ if (defined($excludeClasses{$superClassName})) { # super class is in a parent module
+ my $moduleId = $excludeClasses{$superClassName}{'moduleId'};
+ my $classId = $excludeClasses{$superClassName}{'classId'};
+ next if $casevalues{$moduleId}{$classId};
+ $moduleCases{$moduleId} .= "\t case $classId: return (void*)($superClassName*)($className*)xptr;\n";
+ $casevalues{$moduleId}{$classId} = 1
+ } else {
+ $cur = $moduleclassidx{$superClassName}; # KDE has MI with diamond shaped cycles (cf. KXMLGUIClient)
+ next if $casevalues{0}{$cur}; # ..so skip any duplicate parents
+ $moduleCases{0} .= "\t case $cur: return (void*)($superClassName*)($className*)xptr;\n";
+ $casevalues{0}{$cur} = 1;
+ }
}
+ foreach my $case (keys(%moduleCases)) {
+ print OUT "\t case $case:\n";
+ print OUT "\t switch(to.index) {\n";
+ print OUT "$moduleCases{$case}";
+ print OUT "\t default: return xptr;\n";
+ print OUT "\t }\n";
+ }
print OUT "\t default: return xptr;\n";
print OUT "\t}\n";
} );
@@ -2951,23 +2987,27 @@
# print OUT " void init_${libname}_Smoke();\n";
# print OUT "}\n";
print OUT "\n";
- print OUT "Smoke* ${libname}_Smoke = 0L;\n";
+ my @modules = keys(%parentModules);
+ for (my $i = 0; $i < $#modules; $i++) {
+ print OUT "Smoke *$modules[$i]_Smoke;\n";
+ print OUT "void init_$modules[$i]_Smoke();\n\n";
+ }
+ print OUT "Smoke *${libname}_Smoke = 0;\n";
print OUT "\n";
print OUT "// Create the Smoke instance encapsulating all the above.\n";
print OUT "void init_${libname}_Smoke() {\n";
- my @modules = keys(%parentModules);
- for (my $i = 1; $i <= $#modules; $i++) {
- print OUT " init_$modules[$i]();\n";
+ for (my $i = 0; $i < $#modules; $i++) {
+ print OUT " init_$modules[$i]_Smoke();\n";
}
- print OUT " Smoke* ${libname}_parentModules[] = { 0";
- for (my $i = 1; $i <= $#modules; $i++) {
- print OUT ", $modules[$i]";
+ print OUT " static Smoke *${libname}_parentModules[] = { 0";
+ for (my $i = 0; $i < $#modules; $i++) {
+ print OUT ", $modules[$i]_Smoke";
}
print OUT " };\n";
print OUT " ${libname}_Smoke = new Smoke(\n";
print OUT " \"${libname}\",\n";
print OUT " ${libname}_parentModules, ". int($#modules+1) .",\n";
- print OUT " ${libname}_classes, ".$#classlist.",\n";
+ print OUT " ${libname}_classes, ".$#moduleclasslist.",\n";
print OUT " ${libname}_methods, $methodCount,\n";
print OUT " ${libname}_methodMaps, $methodMapCount,\n";
print OUT " ${libname}_methodNames, $methodNameCount,\n";
--- branches/work/kdebindings-smoke2/smoke/smoke.h #689262:689263
@@ -56,17 +56,19 @@
EnumToLong
};
+ struct ParentIndex; // defined below
+
typedef short Index;
typedef void (*ClassFn)(Index method, void* obj, Stack args);
- typedef void* (*CastFn)(void* obj, Index from, Index to);
+ typedef void* (*CastFn)(void* obj, Index from, ParentIndex to);
typedef void (*EnumFn)(EnumOperation, Index, void*&, long&);
// We could set references to the different Smoke modules in the arrays to avoid
// using an extra struct like ParentIndex. I want to keep those arrays
// reference-free, though.
- // Use moduleIndexFromParentIndex to obtain a ModuleIndex from a Parent Index. -ar
+ // Use moduleIndexFromParentIndex to obtain a ModuleIndex from a ParentIndex. -ar
/**
- * Describe one index in one direct parent module.
+ * Describe one index in one parent module.
*/
struct ParentIndex {
Index parent;
@@ -315,7 +317,17 @@
return ret;
}
- inline void *cast(void *ptr, Index from, Index to) {
+ inline ParentIndex parentIndexFromModuleIndex(ModuleIndex idx) {
+ for (Index i = 0; i < numParentModules; ++i) {
+ if (parentModules[i] == idx.smoke) {
+ ParentIndex ret = { i, idx.index };
+ return ret;
+ }
+ }
+ return NullParentIndex;
+ }
+
+ inline void *cast(void *ptr, Index from, ParentIndex to) {
if(!castFn) return ptr;
return (*castFn)(ptr, from, to);
}
@@ -442,8 +454,6 @@
}
inline ModuleIndex findMethod(ModuleIndex c, ModuleIndex name) {
- // If method is in a parent module, forward the call from here
-
// Index is invalid
if(!c.index || !name.index) return NullModuleIndex;
More information about the Kde-bindings
mailing list