[glibmm/gmmproc-refactor] Various changes in Common::WrapParser.



commit 3460ddffe3fe0070da7c834e668c8a1b7567487b
Author: Krzesimir Nowak <qdlacz gmail com>
Date:   Wed Nov 30 18:16:28 2011 +0100

    Various changes in Common::WrapParser.
    
    Like getters, some method adaptations, most of methods being commented
    out, usage of Common::Output::Gobject, etc. In general - still WIP.

 tools/pm/Common/WrapParser.pm | 2447 ++++++++++++++++++++++++++---------------
 1 files changed, 1548 insertions(+), 899 deletions(-)
---
diff --git a/tools/pm/Common/WrapParser.pm b/tools/pm/Common/WrapParser.pm
index eb1b95b..4693023 100644
--- a/tools/pm/Common/WrapParser.pm
+++ b/tools/pm/Common/WrapParser.pm
@@ -1,3 +1,4 @@
+# -*- mode: perl; perl-indent-level: 2; indent-tabs-mode: nil -*-
 # gmmproc - Common::WrapParser module
 #
 # Copyright 2011 glibmm development team
@@ -21,133 +22,266 @@ package Common::WrapParser;
 
 use strict;
 use warnings;
+
+use IO::File;
+
 use Common::Util;
-use Common::Function;
-use Common::DocsParser;
+use Common::SectionManager;
+use Common::Output::Shared;
+use Common::Output::Gobject;
+use constant
+{
+  'STAGE_HG' => 0,
+  'STAGE_CCG' => 1,
+  'STAGE_INVALID' => 2
+};
 
 ############################################################################
 
-my @tokens = ();
-
-my $g_a = 'api';
-my $g_
+sub nl
+{
+  return (shift or '') . "\n";
+}
 
-sub new($$)
+# public
+sub new ($$$)
 {
-  my $type = shift;
-  my $api = shift;
+  my ($type, $repositories, $gir_namespace) = @_;
   my $class = (ref ($type) or $type or 'Common::WrapParser');
   my $self =
   {
-    $g_m => $api
-  }
+    # TODO: check if all those fields are really needed.
+    'filename' => '(none)',
+    'line_num' => 0,
+    'level' => 0,
+    'class' => '',
+    'c_class' => '',
+    'in_class' => 0,
+    'first_namespace' => 1,
+    'namespace' => [],
+    'in_namespace' => [],
+    'defsdir' => ".",
+    'module' => $gir_namespace,
+    'type' => "GTKOBJECT", # or "BOXEDTYPE", or "GOBJECT" - wrapped differently.
+    'already_read' => {},
+    'repositories' => $repositories,
+    'tokens_hg' => [],
+    'tokens_ccg' => [],
+    'tokens_null' => [],
+    'tokens' => [],
+    'parsing_stage' => STAGE_INVALID,
+    'main_section' => Common::SectionManager::SECTION_DEV_NULL,
+    'section_manager' => Common::SectionManager->new,
+    'stage_section_pairs' =>
+    {
+      STAGE_HG() => [Common::SectionManager::SECTION_H, 'tokens_hg'],
+      STAGE_CCG() => [Common::SectionManager::SECTION_CC, 'tokens_ccg'],
+      STAGE_INVALID() => [Common::SectionManager::SECTION_DEV_NULL, 'tokens_null']
+    },
+    'source_dir' => undef,
+    'destination_dir' => undef,
+    'base' => undef
+  };
+
+  $self = bless ($self, $class);
+  $self->{'handlers'} =
+  {
+    '{' => [$self, \&on_open_brace],
+    '}' => [$self, \&on_close_brace],
+    '`' => [$self, \&on_backtick], # probably won't be needed anymore
+    '\'' => [$self, \&on_apostrophe], # probably won't be needed anymore
+    '"' => [$self, \&on_string_literal],
+    '//' => [$self, \&on_comment_cpp],
+    '/*' => [$self, \&on_comment_c],
+    '/**' => [$self, \&on_comment_doxygen],
+    '#m4begin' => [$self, \&on_m4_section], # probably won't be needed anymore
+    '#m4' => [$self, \&on_m4_line], # probably won't be needed anymore
+    '_DEFS' => [$self, \&on_defs], # probably won't be needed anymore
+    '_IGNORE' => [$self, \&on_ignore],
+    '_IGNORE_SIGNAL' => [$self, \&on_ignore_signal],
+    '_WRAP_METHOD' => [$self, \&on_wrap_method],
+    '_WRAP_METHOD_DOCS_ONLY' => [$self, \&on_wrap_method_docs_only],
+    '_WRAP_CORBA_METHOD'=> [$self, \&on_wrap_corba_method],
+    '_WRAP_SIGNAL' => [$self, \&on_wrap_signal],
+    '_WRAP_PROPERTY' => [$self, \&on_wrap_property],
+    '_WRAP_VFUNC' => [$self, \&on_wrap_vfunc],
+    '_WRAP_CTOR' => [$self, \&on_wrap_ctor],
+    '_WRAP_CREATE' => [$self, \&on_wrap_create],
+    '_WRAP_ENUM' => [$self, \&on_wrap_enum],
+    '_WRAP_GERROR' => [$self, \&on_wrap_gerror],
+    '_IMPLEMENTS_INTERFACE' => [$self, \&on_implements_interface],
+    # TODO: these should be handled by different handlers.
+    '_CLASS_GENERIC' => [$self, \&on_class_generic],
+    '_CLASS_GOBJECT' => [$self, \&on_class_gobject],
+    '_CLASS_GTKOBJECT' => [$self, \&on_class],
+    '_CLASS_BOXEDTYPE' => [$self, \&on_class],
+    '_CLASS_BOXEDTYPE_STATIC' => [$self, \&on_class],
+    '_CLASS_INTERFACE' => [$self, \&on_class],
+    '_CLASS_OPAQUE_COPYABLE' => [$self, \&on_class],
+    '_CLASS_OPAQUE_REFCOUNTED' => [$self, \&on_class],
+    'namespace' => [$self, \&on_namespace],
+    '_INSERT_SECTION' => [$self, \&on_insert_section]
+  };
+
+
+
+  return bless ($self, $class);
+}
 
-   #Initialize member data:
-  $$self{objOutputter} = $objOutputter;
-  $$self{filename} = "(none)";
-  $$self{line_num} = 0;
+# public
+sub set_source_dir ($$)
+{
+  my ($self, $source_dir) = @_;
 
-  $$self{level} = 0;
-  $$self{class} = "";
-  $$self{c_class} = "";
-  $$self{in_class} = 0;
-  $$self{first_namespace} = 1;
-  $$self{namespace} = [];
-  $$self{in_namespace} = [];
+  $self->{'source_dir'} = $source_dir;
+}
 
-  $$self{defsdir} = ".";
+# public
+sub set_destination_dir ($$)
+{
+  my ($self, $destination_dir) = @_;
 
-  $$self{module} = ""; #e.g. "gtkmm"
+  $self->{'destination_dir'} = $destination_dir;
+}
 
-  $$self{type} = "GTKOBJECT"; # or "BOXEDTYPE", or "GOBJECT" - wrapped differently.
+# public
+sub set_base ($$)
+{
+  my ($self, $base) = @_;
 
-  $$self{already_read} = {};
+  $self->{'base'} = $base;
+}
 
-  bless ($self, $class);
-  return $self;
+# public
+sub get_namespaces ($)
+{
+  my ($self) = @_;
+
+  return $self->{'namespace'};
 }
 
-# void parse_and_build_output()
-sub parse_and_build_output($)
+# public
+sub get_section_manager ($)
 {
   my ($self) = @_;
 
-  my $objOutputter = $$self{objOutputter};
+  return $self->{'section_manager'};
+}
+
+# public
+sub get_main_section ($)
+{
+  my ($self) = @_;
 
-  # Parse the tokens.
-  my $token;
-  while ( scalar(@tokens) )
+  return $self->{'main_section'};
+}
+
+sub switch_to_stage ($$)
+{
+  my ($self, $stage) = @_;
+  my $pairs = $self->{'stage_section_pairs'};
+
+  if (exists $pairs->{$stage})
   {
-    $token = $self->extract_token();
-    my $bAppend = 1;
-
-    # we need to monitor the depth of braces
-    if ($token eq '{')         { $self->on_open_brace(); }
-    if ($token eq '}')         { $self->on_close_brace(); $bAppend = 0;}
-
-    # protect `' from the source file from m4
-    if ($token eq "`")         { $objOutputter->append("`'__BT__`'"); next; }
-    if ($token eq "'")         { $objOutputter->append("`'__FT__`'"); next; }
-
-    if ($token eq '"')         { $objOutputter->append($self->on_string_literal()); next; }
-    if ($token eq '//')        { $objOutputter->append($self->on_comment_cpp()); next; }
-    if ($token eq '/*')        { $objOutputter->append($self->on_comment_c()); next; }
-    if ($token eq '/**')       { $self->on_comment_doxygen(); next; }
-
-    # handle #m4begin ... #m4end
-    if ($token eq "#m4begin")  { $objOutputter->append($self->on_m4_section()); next;}
-
-    # handle #m4 ... \n
-    if ($token eq "#m4")       { $objOutputter->append($self->on_m4_line()); next;}
-
-    if ($token eq "_DEFS")     { $self->on_defs(); next;} #Read the defs file.
-    if ($token eq "_IGNORE")     { $self->on_ignore(); next;} #Ignore a function.
-    if ($token eq "_IGNORE_SIGNAL")     { $self->on_ignore_signal(); next;} #Ignore a signal.
-    if ($token eq "_WRAP_METHOD")     { $self->on_wrap_method(); next;}
-    if ($token eq "_WRAP_METHOD_DOCS_ONLY")     { $self->on_wrap_method_docs_only(); next;}
-    if ($token eq "_WRAP_CORBA_METHOD")     { $self->on_wrap_corba_method(); next;} #Used in libbonobo*mm.
-    if ($token eq "_WRAP_SIGNAL") { $self->on_wrap_signal(0); next;}
-    if ($token eq "_WRAP_PROPERTY") { $self->on_wrap_property(); next;}
-    if ($token eq "_WRAP_VFUNC") { $self->on_wrap_vfunc(); next;}
-    if ($token eq "_WRAP_CTOR")   { $self->on_wrap_ctor(); next;}
-    if ($token eq "_WRAP_CREATE") { $self->on_wrap_create(); next;}
-
-    if ($token eq "_WRAP_ENUM")   { $self->on_wrap_enum(); next;}
-    if ($token eq "_WRAP_GERROR") { $self->on_wrap_gerror(); next;}
-    if ($token eq "_IMPLEMENTS_INTERFACE") { $self->on_implements_interface(); next;}
-
-    if ($token =~ m/\A_CLASS_/s)
-    {
-      $self->on_class($token);
-      next;
+    $self->{'parsing_stage'} = $stage;
+    $self->{'main_section'} = $pairs->{$stage}[0];
+    $self->{'tokens'} = $self->{$pairs->{$stage}[1]};
+  }
+  else
+  {
+    # TODO: internal error.
+  }
+}
 
-      # e.g.:
-      # _CLASS_GENERIC
-      # _CLASS_GOBJECT
-      # _CLASS_GTKOBJECT
-      # _CLASS_BOXEDTYPE
-      # _CLASS_BOXEDTYPE_STATIC
-      # _CLASS_INTERFACE
-      # _CLASS_OPAQUE_COPYABLE
-      # _CLASS_OPAQUE_REFCOUNTED
-    }
+# public
+sub parse ($)
+{
+  my ($self) = @_;
+
+  $self->read_file;
+  $self->parse_and_build_output;
+}
+
+# void parse_and_build_output()
+sub parse_and_build_output ($)
+{
+  my ($self) = @_;
+  my $handlers = $self->{'handlers'};
+  my $section_manager = $self->{'section_manager'};
+  my @stages = (STAGE_HG, STAGE_CCG);
+
+  for my $stage (@stages)
+  {
+    $self->switch_to_stage ($stage);
 
-    if ($token eq "namespace") { $self->on_namespace() };
+    my $tokens = $self->{'tokens'};
 
-    # After all token manipulations
-    if($bAppend)
+    while (@{$tokens})
     {
-      $objOutputter->append($token);
+      my $token = $self->extract_token;
+
+      if (exists $handlers->{$token})
+      {
+        my $pair = $handlers->{$token};
+        my $object = $pair->[0];
+        my $handler = $pair->[1];
+
+        if (defined $object)
+        {
+          $object->$handler;
+        }
+        else
+        {
+          &{$handler};
+        }
+      }
+      else
+      {
+        my $main_section = $self->{'main_section'};
+        # no handler found - just paste the token to main section
+        $section_manager->append_string_to_section ($token, $main_section);
+      }
     }
   }
+
+  my $destination_dir = $self->{'destination_dir'};
+  my $base = $self->{'base'};
+  my $h_file = File::Spec->catfile ($destination_dir, $base . '.h');
+  my $cc_file = File::Spec->catfile ($destination_dir, $base . '.cc');
+  my $p_h_file = File::Spec->catfile ($destination_dir, 'private', $base . '_p.h');
+
+  $section_manager->write_main_section_to_file (Common::SectionManager::SECTION_H, $h_file);
+  $section_manager->write_main_section_to_file (Common::SectionManager::SECTION_CC, $cc_file);
+  $section_manager->write_main_section_to_file (Common::SectionManager::SECTION_P_H, $p_h_file);
 }
 
-sub error($$)
+sub error_with_loc ($$$)
 {
-  my ($self, $format) = @_;
+  my ($self, $line_num, $message) = @_;
 
-  $format = "$$self{filename}:$$self{line_num}: $format";
-  printf STDERR $format,@_;
+  print STDERR $self->{'filename'} . ':' . $line_num . ' - ERROR: ' . $message . "\n";
+  exit 1;
+}
+
+sub error ($$)
+{
+  my ($self, $message) = @_;
+
+  $self->error_with_loc ($self->{'line_num'}, $message);
+}
+
+sub warning_with_loc ($$$)
+{
+  my ($self, $line_num, $message) = @_;
+
+  print STDERR $self->{'filename'} . ':' . $line_num . ' - WARNING: ' . $message;
+}
+
+sub warning ($$)
+{
+  my ($self, $message) = @_;
+
+  $self->warning_with_loc ($self->{'line_num'}, $message);
 }
 
 ######################################################################
@@ -156,216 +290,162 @@ sub error($$)
 ########################################
 ###  returns the next token, ignoring some stuff.
 # $string extract_token()
-sub extract_token($)
+sub extract_token ($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
 
-  while ( scalar(@tokens) )
+  while (@{$tokens})
   {
-    $_ = shift @tokens;
+    my $token = shift @{$tokens};
 
     # skip empty tokens
-    next if ( !defined($_) or $_ eq "" );
-
-    # eat line statements
-    if (m/^#l (\S+)\n/)
-    {
-      $$self{line_num} = $1;
-      next;
-    }
+    next if (not defined ($token) or $token eq '');
 
-    # eat file statements
-    if (m/^#f (\S+)\n/)
+    if ($token =~ /\n/)
     {
-      $$self{filename} = $1;
-      next;
+      ++$self->{'line_num'};
     }
 
-    return $_;
-   }
+    return $token;
+  }
 
-  return "";
+  return '';
 }
 
 ### Returns the next token, but does not remove it from the queue, so that
 # extract_token will return it again.
 # $string peek_token()
-sub peek_token($)
+sub peek_token ($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
 
-  while ( scalar(@tokens) )
+  while (@{$tokens})
   {
-    $_ = $tokens[0];
+    my $token = $tokens->[0];
 
     # skip empty tokens
-    if(!defined($_) or $_ eq "")
+    if (not defined $token or $token eq '')
     {
-      shift @tokens;
-    }
-    # eat line statements
-    elsif ( /^#l (\S+)\n/)
-    {
-      $$self{line_num} = $1;
-      shift @tokens;
-    }
-    # eat file statements
-    elsif ( /^#f (\S+)\n/)
-    {
-      $$self{filename} = $1;
-      shift @tokens;
+      shift @{$tokens};
     }
     else
     {
-      return $_;
+      return $token;
     }
   }
 
-  return "";
+  return '';
 }
 
-# bool tokens_remaining()
-sub tokens_remaining($)
+sub on_string_with_delimiters ($$$$)
 {
-  my ($self) = @_;
-  return $#tokens >= 0;
-}
+  my ($self, $start, $end, $what) = @_;
+  my $tokens = $self->{'tokens'};
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
+  my @out = ($start);
+  my $line_num = $self->{'line_num'};
+
+  while (@{$tokens})
+  {
+    my $token = $self->extract_token;
 
+    push @out, $token;
+    if ($token eq $end)
+    {
+      $section_manager->append_string_to_section (join ('', @out), $main_section);
+      return;
+    }
+  }
+  $self->error_with_loc ($line_num, 'Hit eof while in ' . $what . '.');
+}
 
 ########################################
 ###  we pass strings literally with quote substitution
 # void on_string_literal()
-sub on_string_literal($)
+sub on_string_literal ($)
 {
   my ($self) = @_;
 
-  my @out;
-  push (@out, '"');
-  while ( scalar(@tokens) )
-  {
-    $_ = $self->extract_token();
-    if ($_ eq "`") { push(@out, "`'__BT__`'"); next; }
-    if ($_ eq "'") { push(@out, "`'__FT__`'"); next; }
-    push (@out, $_);
-
-    return join("",@out) if ($_ eq '"');
-  }
-
-  my $line_num = $$self{line_num};
-  my $filename = $$self{filename};
-  print STDERR "$filename:$line_num: Hit eof while in string\n";
+  $self->on_string_with_delimiters ('"', '"', 'string');
 }
 
 
 ########################################
-###  we pass comments literally with quote substitution
+###  we pass comments literally
 # void on_comment_cpp()
-sub on_comment_cpp($)
+sub on_comment_cpp ($)
 {
   my ($self) = @_;
 
-  my @out;
-  push (@out,"//\`");
-  while ( scalar(@tokens) )
-  {
-    $_ = $self->extract_token();
-    if ($_ eq "`") { push(@out,"\'__BT__\`"); next; }
-    if ($_ eq "'") { push(@out,"\'__FT__\`"); next; }
-    if ($_ eq "\n")
-    {
-      push (@out,"\'\n");
-      return join("",@out)
-    }
-
-    if ($_ =~ /^_[A-Z]+$/) {$_="_$_";}  # wipe out potential macros
-
-    push (@out,$_);
-  }
+  $self->on_string_with_delimiters ('//', "\n", 'C++ comment');
 }
 
 
 ########################################
-###  we pass C comments literally with quote substitution
+###  we pass C comments literally
 # void on_comment_c()
-sub on_comment_c($)
+sub on_comment_c ($)
 {
   my ($self) = @_;
 
-  my @out;
-  push (@out,"/*\`");
-  while ( scalar(@tokens) )
-  {
-    $_ = $self->extract_token();
-    if ($_ eq "`") { push(@out,"\'__BT__\`"); next; }
-    if ($_ eq "'") { push(@out,"\'__FT__\`"); next; }
-    if ($_ eq "*/")
-    {
-      push (@out,"\'*/");
-      return join("",@out)
-    }
-
-    push (@out,$_);
-  }
+  $self->on_string_with_delimiters ('/*', '*/', 'C comment');
 }
 
-sub on_comment_doxygen($)
+sub on_comment_doxygen ($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
+  my @out =  ('/**');
+  my $line_num = $self->{'line_num'};
 
-  my $objOutputter = $$self{objOutputter};
-
-  my @out;
-  push (@out,"/**\`");
-  while ( scalar(@tokens) )
+  while (@{$tokens})
   {
-    $_ = $self->extract_token();
-    if ($_ eq "`") { push(@out,"\'__BT__\`"); next; }
-    if ($_ eq "'") { push(@out,"\'__FT__\`"); next; }
+    my $token = $self->extract_token;
 
-    if ($_ eq "*/")
+    if ($token eq '*/')
     {
-      push (@out,"\'*");
-      $objOutputter->append(join("", @out));
-
+      push @out, '*';
       # Find next non-whitespace token, but remember whitespace so that we
       # can print it if the next real token is not _WRAP_SIGNAL
-      my @whitespace;
-      my $next_token = $self->peek_token();
+      my @whitespace = ();
+      my $next_token = $self->peek_token;
       while ($next_token !~ /\S/)
       {
-        push(@whitespace, $self->extract_token());
-        $next_token = $self->peek_token();
+        push @whitespace, $self->extract_token;
+        $next_token = $self->peek_token;
       }
 
       # If the next token is a signal, do not close this comment, to merge
       # this doxygen comment with the one from the signal.
-      if($next_token eq '_WRAP_SIGNAL')
+      if ($next_token eq '_WRAP_SIGNAL')
       {
         # Extract token and process
         $self->extract_token();
         # Tell wrap_signal to merge automatically generated comment with
         # already existing comment. This is why we do not close the comment
         # here.
-        $self->on_wrap_signal(1);
+        return $self->on_wrap_signal_after_comment(\ out);
       }
       else
       {
         # Something other than signal follows, so close comment normally
-        $objOutputter->append("/");
-        # And append whitespace we ignored so far
-        $objOutputter->append(join("", @whitespace));
-        # Do not extract the token so that parse_and_build_output() will
-        # process it.
+        # and append whitespace we ignored so far.
+        push @out, '/', @whitespace;
+        return join '', @out;
       }
 
       last;
     }
 
-    push (@out,$_);
+    push @out, $token;
   }
+  $self->error_with_loc ($line_num, 'Hit eof while in doxygen comment.');
 }
 
-
+#TODO: get rid of it?
 ########################################
 ###  handle #m4begin ... #m4end
 # we don't substitute ` or ' in #m4begin
@@ -373,24 +453,20 @@ sub on_comment_doxygen($)
 sub on_m4_section($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
+  my $line_num = $self->{'line_num'};
 
-  my @value;
-  my $token;
+  $self->warning ('#m4begin and #m4end are deprecated.');
 
-  while ( scalar(@tokens) )
+  while (@{$tokens})
   {
-    $token = $self->extract_token();
-    return join("", @value) if ($token eq "#m4end");
-    push(@value, $token);
+    return if ($self->extract_token eq '#m4end');
   }
 
-  my $line_num = $$self{line_num};
-  my $filename = $$self{filename};
-  print STDERR "$filename:$line_num: Hit eof looking for #m4end\n";
-  next;
+  $self->error_with_loc ($line_num, 'Hit eof when looking for #m4end.');
 }
 
-
+# TODO: get rid of it?
 ########################################
 ###  handle #m4 ... /n
 # we don't substitute ` or ' in #m4
@@ -398,242 +474,290 @@ sub on_m4_section($)
 sub on_m4_line ($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
+  my $line_num = $self->{'line_num'};
 
-  my @value;
-  my $token;
-  while ( scalar(@tokens) )
+  $self->warning ('#m4 is deprecated.');
+
+  while (@{$tokens})
   {
-    $token = $self->extract_token();
-    push(@value,$token); # push first, so we don't eat the newline
-    return join("",@value) if ($token eq "\n");
+    return if ($self->extract_token eq "\n");
   }
-}
 
+  $self->error_with_loc ($line_num, 'Hit eof when looking for newline');
+}
 
 ########################################
 # m4 needs to know when we entered a namespace
 # void on_namespace()
-sub on_namespace($)
+sub on_namespace ($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
-
-  my $number = 0;
-  my $token;
-  my $arg;
+  my $tokens = $self->{'tokens'};
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
+  my $name = '';
+  my $done = 0;
+  my $in_s_comment = 0;
+  my $in_m_comment = 0;
+  my $line_num = $self->{'line_num'};
 
   # we need to peek ahead to figure out what type of namespace
   # declaration this is.
-  while ( $number <= $#tokens )
+  foreach my $token (@{$tokens})
   {
-    $token = $tokens[$number];
-    $number++;
-    next if (!defined($token) or $token eq "");
-#      print "> $token\n";
+    next if (not defined $token or $token eq '');
 
-    if ($token eq '{')
+    if ($in_s_comment)
+    {
+      if ($token eq "\n")
+      {
+        $in_s_comment = 0;
+      }
+    }
+    elsif ($in_m_comment)
+    {
+      if ($token eq '*/')
+      {
+        $in_m_comment = 0;
+      }
+    }
+    elsif ($token eq '//')
+    {
+      $in_s_comment = 1;
+    }
+    elsif ($token eq '/*' or $token eq '/**')
+    {
+      $in_m_comment = 1;
+    }
+    elsif ($token eq '{')
     {
-      $arg = Util::string_trim($arg);
+      $name = Util::string_trim ($name);
 
-      if ($$self{first_namespace})
+      if ($self->{'first_namespace'})
       {
-        $objOutputter->append("_SECTION(SECTION_HEADER2)\n");
-        $$self{first_namespace} = 0;
+        $self->{'first_namespace'} = 0;
+        $section_manager->append_section_to_section ('SECTION_BEFORE_FIRST_NAMESPACE', $main_section);
       }
 
-      $objOutputter->append("_NAMESPACE($arg)");
-      unshift(@{$$self{namespace}}, $arg);
-      unshift(@{$$self{in_namespace}}, $$self{level}+1);
-      return;
+#      this is probably not needed - m4 needed that to know what namespaces
+#      were opened, so it could close them and reopen in order
+#      $objOutputter->append("_NAMESPACE($arg)");
+      unshift @{$self->{'namespace'}}, $name;
+      unshift @{$self->{'in_namespace'}}, $self->{'level'} + 1;
+      $done = 1;
+    }
+    elsif ($token eq ';')
+    {
+      $done = 1;
+    }
+    elsif ($token !~ /\s/)
+    {
+      if ($name ne '')
+      {
+        $self->error ('Unexpected `' . $token . '\' after namespace name.');
+      }
+      $name = $token;
     }
 
-    next if ( $token =~ /^#[lf] \S+\n/);
-    return if ($token eq ';');
-
-    $arg .= $token; #concatenate
+    if ($done)
+    {
+      $section_manager->append_string_to_section ('namespace', $main_section);
+      return;
+    }
   }
+  $self->error_with_loc ($line_num, 'Hit eof while processing `namespace\'.');
 }
 
 
+# TODO: implement it.
 ########################################
 ###  we don't want to report every petty function as unwrapped
 # void on_ignore($)
 sub on_ignore($)
 {
   my ($self) = @_;
-  my $str = $self->extract_bracketed_text();
-  my @args = split(/\s+|,/,$str);
-  foreach (@args)
-  {
-    next if ($_ eq "");
-    GtkDefs::lookup_function($_); #Pretend that we've used it.
-  }
+
+  $self->warning ('_IGNORE is not yet implemented.');
+  $self->extract_bracketed_text;
+#  my @args = split(/\s+|,/,$str);
+#  foreach (@args)
+#  {
+#    next if ($_ eq "");
+#    GtkDefs::lookup_function($_); #Pretend that we've used it.
+#  }
 }
 
+# TODO: implement it.
 sub on_ignore_signal($)
 {
   my ($self) = @_;
-  my $str = $self->extract_bracketed_text();
-  $str = Util::string_trim($str);
-  $str = Util::string_unquote($str);
-  my @args = split(/\s+|,/,$str);
-  foreach (@args)
-  {
-    next if ($_ eq "");
-    GtkDefs::lookup_signal($$self{c_class}, $_); #Pretend that we've used it.
-  }
+
+  $self->warning ('_IGNORE_SIGNAL is not yet implemented.');
+  $self->extract_bracketed_text;
+#  $str = Util::string_trim($str);
+#  $str = Util::string_unquote($str);
+#  my @args = split(/\s+|,/,$str);
+#  foreach (@args)
+#  {
+#    next if ($_ eq "");
+#    GtkDefs::lookup_signal($$self{c_class}, $_); #Pretend that we've used it.
+#  }
 }
 
+# TODO: make it a common handler of _CLASS macros. And actually implement it.
 ########################################
 ###  we have certain macros we need to insert at end of statements
 # void on_class($, $strClassCommand)
-sub on_class($$)
+#sub on_class($$)
+sub on_class ($)
 {
-  my ($self, $class_command) = @_;
-
-  my $objOutputter = $$self{objOutputter};
-
-  $$self{in_class} = $$self{level};
-
-  #Remember the type of wrapper required, so that we can append the correct _END_CLASS_* macro later.
-  {
-    my $str = $class_command;
-    $str =~ s/^_CLASS_//;
-    $$self{type} = $str;
-  }
+#  my ($self, $class_command) = @_;
+  my ($self) = @_;
 
-  my $str = $self->extract_bracketed_text();
-  my ($class, $c_class) = split(',',$str);
-  $class = Util::string_trim($class);
-  $c_class = Util::string_trim($c_class);
+  $self->warning ('on_class is not implemented.');
+  $self->extract_bracketed_text;
 
-  $$self{class} = $class;
-  $$self{c_class} = $c_class;
+  # my $objOutputter = $$self{objOutputter};
 
-  my @back;
-  push(@back, $class_command);
-  push(@back, "($str)");
+  # $$self{in_class} = $$self{level};
 
-  # When we hit _CLASS, we walk backwards through the output to find "class"
-  my $token;
-  while ( scalar(@{$$objOutputter{out}}))
-  {
-    $token = pop @{$$objOutputter{out}};
-    unshift(@back, $token);
-    if ($token eq "class")
-    {
-      $objOutputter->append("_CLASS_START()");
+  # #Remember the type of wrapper required, so that we can append the correct _END_CLASS_* macro later.
+  # {
+  #   my $str = $class_command;
+  #   $str =~ s/^_CLASS_//;
+  #   $$self{type} = $str;
+  # }
 
-      my $strBack = join("", @back);
+  # my ($class, $c_class) = split(',',$str);
+  # $class = Util::string_trim($class);
+  # $c_class = Util::string_trim($c_class);
 
-      $objOutputter->append($strBack);
-      return;
-    }
-  }
+  # $$self{class} = $class;
+  # $$self{c_class} = $c_class;
 
-  $self->error("$class_command outside of class.\n");
-  exit(-1);
-}
+  # my @back;
+  # push(@back, $class_command);
+  # push(@back, "($str)");
 
-# remove surround spaces from the string
-sub trim($)
-{
-    my $string = shift;
-    $string =~ s/^\s+//;
-    $string =~ s/\s+$//;
-    return $string;
+  # TODO: do we really need it?
+  # When we hit _CLASS, we walk backwards through the output to find "class"
+  # my $token;
+  # while ( scalar(@{$$objOutputter{out}}))
+  # {
+  #   $token = pop @{$$objOutputter{out}};
+  #   unshift(@back, $token);
+  #   if ($token eq "class")
+  #   {
+  #     $objOutputter->append("_CLASS_START()");
+
+  #     my $strBack = join("", @back);
+
+  #     $objOutputter->append($strBack);
+  #     return;
+  #   }
+  # }
+
+#  $self->error($class_command . 'outside of class.');
+#  exit 1;
 }
 
 # order to read the defs file
 # void on_defs()
-sub on_defs($)
+sub on_defs ($)
 {
   my ($self) = @_;
 
-  my $str = $self->extract_bracketed_text();
-  my ($module, $defsfile) = split(/,/, $str); #e.g. _DEFS(gtkmm,gtk), where gtkmm is the module name, and gtk is the defs file name.
-  $module = trim($module);
-  $defsfile = trim($defsfile);
-  my $already_parsed = $$self{already_read};
-
-  if (exists ($already_parsed->{$defsfile}))
-  {
-    print join ('', $defsfile, '.defs already parsed.', "\n");
-    return;
-  }
-  $already_parsed->{$defsfile} = 1;
-
-  # $$self{section} = $section;  #Save it so that we can reuse it in read_defs_included.
-  $$self{module} = $module; #Use it later in call to output_temp_g1().
-
-  GtkDefs::read_defs("$$self{defsdir}", "$defsfile.defs");
-
-  #Read the documentation too, so that we can merge it into the generated C++ code:
-  my $docs_filename = $defsfile . "_docs.xml";
-  my $docs_filename_override = $defsfile . "_docs_override.xml";
-  DocsParser::read_defs("$$self{defsdir}", $docs_filename, $docs_filename_override);
+  $self->warning ('_DEFS macro is deprecated.');
+  $self->extract_bracketed_text;
 }
 
 # void on_open_brace()
 sub on_open_brace($)
 {
   my ($self) = @_;
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
 
-  $$self{level}++;
+  ++$self->{'level'};
+  $section_manager->append_string_to_section ('{', $main_section);
 }
 
 # void on_close_brace($)
 sub on_close_brace($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
 
-  #push(@out, "($$self{level})");
-
-  $self->on_end_class()
-    if ($$self{in_class} && $$self{in_class} == $$self{level});
+  if ($self->{'in_class'} and $self->{'in_class'} == $self->{'level'})
+  {
+    $self->on_end_class();
+  }
 
-  $objOutputter->append("}"); #We append it here instead of after we return, so that we can end the namespace after it.
+  $section_manager->append_string_to_section ('}', $main_section);
 
-  $self->on_end_namespace()
-    if ( scalar(@{$$self{in_namespace}}) && (@{$$self{in_namespace}}[0] == $$self{level}) );
+  if (@{$self->{'in_namespace'}} and $self->{'in_namespace'}[0] == $self->{'level'})
+  {
+    $self->on_end_namespace();
+  }
 
-  $$self{level}--;
+  --$self->{'level'};
 }
 
 
+# TODO: check if we really need it. That was probably only for m4. We can do it in simpler way.
 ########################################
 ###  denote the end of a class
 # void on_end_class($)
-sub on_end_class($)
+sub on_end_class ($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
-
-  # Examine $$self{type}, which was set in on_class()
-  # And append the _END_CLASS_* macro, which will, in turn, output the m4 code.
-  {
-    my $str = $$self{type};
-    $objOutputter->append("`'_END_CLASS_$str()\n");
-  }
-
-  $$self{class} = "";
-  $$self{c_class} = "";
-  $$self{in_class} = 0;
+  # my $objOutputter = $$self{objOutputter};
+
+  # # Examine $$self{type}, which was set in on_class()
+  # # And append the _END_CLASS_* macro, which will, in turn, output the m4 code.
+  # {
+  #   my $str = $$self{type};
+  #   $objOutputter->append("`'_END_CLASS_$str()\n");
+  # }
+
+  # $$self{class} = "";
+  # $$self{c_class} = "";
+  # $$self{in_class} = 0;
 }
 
-
 ########################################
 ###
 # void on_end_namespace($)
-sub on_end_namespace($)
+sub on_end_namespace ($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
+  my $namespaces = $self->{'namespace'};
+#  my $objOutputter = $$self{objOutputter};
 
-  $objOutputter->append("`'_END_NAMESPACE()");
-  shift( @{$$self{namespace}} );
-  shift( @{$$self{in_namespace}} );
+#  $objOutputter->append("`'_END_NAMESPACE()");
+  shift @{$namespaces};
+  shift @{$self->{'in_namespace'}};
+
+  unless (@{$namespaces})
+  {
+    my $section_manager = $self->{'section_manager'};
+    my $main_section = $self->{'main_section'};
+    my $tokens = $self->{'tokens'};
+    my @strs = ();
+
+    # TODO: make it multiline comments aware?
+    while (@{$tokens})
+    {
+      my $token = $self->extract_token;
+
+      push @strs, $token;
+      last if ($token eq "\n");
+    }
+    $section_manager->append_string_to_section (join ('', @strs), $main_section);
+    $section_manager->append_section_to_section ('SECTION_AFTER_FIRST_NAMESPACE', $main_section);
+  }
 }
 
 
@@ -643,164 +767,176 @@ sub on_end_namespace($)
 ########################################
 ###  takes (\S+) from the tokens (smart)
 # $string extract_bracketed_text()
-sub extract_bracketed_text($)
+sub extract_bracketed_text ($)
 {
   my ($self) = @_;
-
+  my $tokens = $self->{'tokens'};
   my $level = 1;
-  my $str = "";
+  my $str = '';
+  my $line_num = $self->{'line_num'};
 
   # Move to the first "(":
-  while ( scalar(@tokens) )
-    {
-      my $t = $self->extract_token();
-      last if ($t eq "(");
-    }
+  while (@{$tokens})
+  {
+    my $token = $self->extract_token;
+
+    last if ($token eq '(');
+  }
 
   # Concatenate until the corresponding ")":
-  while ( scalar(@tokens) )
-    {
-      my $t = $self->extract_token();
-      $level++ if ($t eq "(");
-      $level-- if ($t eq ")");
+  while (@{$tokens})
+  {
+    my $token = $self->extract_token;
+    ++$level if ($token eq '(');
+    --$level if ($token eq ')');
 
-      return $str if (!$level);
-      $str .= $t;
-    }
+    return $str unless $level;
+    $str .= $token;
+  }
 
-  return "";
+  $self->error_with_loc ($line_num, 'Hit eof when extracting bracketed text.');
 }
 
-
+# TODO: Handle case when some string is passed?
 ########################################
 ###  breaks up a string by commas (smart)
 # @strings string_split_commas($string)
-sub string_split_commas($)
+sub string_split_commas ($)
 {
   my ($in) = @_;
-
-  my @out;
+  my @out = ();
   my $level = 0;
-  my $str = "";
-  my @in = split(/([,()])/, $in);
+  my $str = '';
+  my @tokens = split(/([,()]"')/, $in);
+  my $sq = 0;
+  my $dq = 0;
 
-  while ($#in > -1)
-    {
-      my $t = shift @in;
-
-      next if ($t eq "");
-      $level++ if ($t eq "(");
-      $level-- if ($t eq ")");
+  while (@tokens)
+  {
+    my $token = shift @tokens;
 
-      # skip , inside functions  Ie.  void (*)(int,int)
-      if ( ($t eq ",") && !$level)
-        {
-          push(@out, $str);
-          $str="";
-          next;
-        }
+    next if ($token eq '');
 
-      $str .= $t;
+    if ($sq)
+    {
+      if ($token eq '\'')
+      {
+        $sq = 0;
+      }
+    }
+    elsif ($dq)
+    {
+      if ($token eq '"')
+      {
+        $dq = 0;
+      }
+    }
+    elsif ($token eq '\'')
+    {
+      $sq = 1;
+    }
+    elsif ($token eq '"')
+    {
+      $dq = 1;
+    }
+    elsif ($token eq '(')
+    {
+      ++$level;
+    }
+    elsif ($token eq ')')
+    {
+      --$level;
+    }
+    elsif ($token eq ',' and not $level)
+    {
+      push @out, $str;
+      $str = '';
+      next;
     }
 
-  push(@out,$str);
+    $str .= $token;
+  }
+
+  push @out, $str;
   return @out;
 }
 
+sub tokenize_contents ($$)
+{
+  my ($self, $contents) = @_;
+  # Break the file into tokens.  Token is:
+  # - any group of #, A to z, 0 to 9, _
+  # - /**
+  # - /*
+  # - *.
+  # - //
+  # - any char proceeded by \
+  # - symbols ;{}"`'()
+  # - newline
+  my @tokens = split(/([#A-Za-z0-9_]+)|(\/\*\*)|(\/\*)|(\*\/)|(\/\/)|(\\.)|([;{}"'`()])|(\n)/,
+                     $contents);
+
+  return \ tokens;
+}
 
 ########################################
 ###  reads in the preprocessor files
 # we insert line and file directives for later stages
 # void read_file()
-sub read_file($$$)
+sub read_file ($)
 {
-  my ($self, $srcdir, $source) = @_;
-
-  my $lineno = 1;
-  my @in = ();
-
-  if ( ! -r "${srcdir}/${source}.hg")
+  my ($self) = @_;
+  my $source_dir = $self->{'source_dir'};
+  my $base = $self->{'base'};
+  my $source = File::Spec->catfile ($source_dir, $base);
+  my $hg = $source . '.hg';
+  my $ccg = $source . '.ccg';
+  my $fd = IO::File->new ($hg, 'r');
+
+  unless (defined $fd)
   {
-    print "Unable to find header file $srcdir/$source.hg\n";
-    exit(1);
+    print 'Could not open file `' . $hg . '\' for reading.' . "\n";
+    exit 1;
   }
 
-  # Read header file:
-  open(FILE, "${srcdir}/${source}.hg");
-  push(@in, "#f ${source}.hg\n");
-  while (<FILE>)
-    {
-      push(@in, "#l $lineno\n");
-      push(@in, $_);
-      ++$lineno;
-    }
-  close(FILE);
-  push(@in, "\n", "_SECTION(SECTION_SRC_CUSTOM)\n");
+  $self->{'tokens_hg'} = $self->tokenize_contents (join '', $fd->getlines);
+  $fd->close;
 
   # Source file is optional.
-  if ( -r "${srcdir}/${source}.ccg")
+  $fd = IO::File->new ($ccg, 'r');
+  if (defined $fd)
   {
-    open(FILE, "${srcdir}/${source}.ccg");
-    $lineno = 1;
-    push(@in, "#f ${source}.ccg\n");
-    while (<FILE>)
-      {
-        push(@in, "#l $lineno\n");
-        push(@in, $_);
-        ++$lineno;
-      }
-    close(FILE);
+    my $str = join ('',
+                    '_INSERT_SECTION(SECTION_CCG_BEGIN)',
+                    "\n",
+                    $fd->getlines,
+                    "\n",
+                    '_INSERT_SECTION(SECTION_CCG_END)',
+                    "\n");
+    $self->{'tokens_ccg'} = $self->tokenize_contents ($str);
+    $fd->close;
   }
-
-  my $strIn = join("", @in);
-
-  # Break the file into tokens.  Token is
-  #      any group of #, A to z, 0 to 9, _
-  #      /**
-  #      /*
-  #      *.
-  #      //
-  #      any char proceeded by \
-  #      symbols ;{}"`'()
-  #      newline
-  @tokens = split(/(\#[lf] \S+\n)|([#A-Za-z0-9_]+)|(\/\*\*)|(\/\*)|(\*\/)|(\/\/)|(\\.)|([;{}"'`()])|(\n)/,
-                         $strIn);
-}
-
-
-sub class_prefix($)
-{
-  my ($self) = @_;
-
-  my $str = $$self{class};
-  $str =~ s/([a-z])([A-Z])/$1_$2/g;
-  $str =~ tr/A-Z/a-z/;
-  return $str;
 }
 
-
 ######################################################################
 ##### 2.1 subroutines for _WRAP
 
 ########################################
 
 # $bool check_for_eof()
-sub check_for_eof($)
+sub check_for_eof ($)
 {
   my ($self) = @_;
+  my $tokens = $self->{'tokens'};
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
-
-  unless (scalar(@tokens))
+  unless (@{$tokens})
   {
-    print STDERR "$filename:$line_num:hit eof in _WRAP\n";
-    return 0; #EOF
+    $self->error ('Hit eof in _WRAP.');
   }
-
-  return 1; # No EOF
+  return 1;
 }
 
+# TODO: check if we can avoid using it.
 # Look back for a Doxygen comment.  If there is one,
 # remove it from the output and return it as a string.
 sub extract_preceding_documentation ($)
@@ -836,626 +972,1139 @@ sub extract_preceding_documentation ($)
   return $comment;
 }
 
+# TODO: implement it.
 # void on_wrap_method()
 sub on_wrap_method($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
 
-  return unless ($self->check_for_eof());
+  $self->extract_bracketed_text;
+  # my $objOutputter = $$self{objOutputter};
+
+  # return unless ($self->check_for_eof());
+
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
+
+  # my $commentblock = $self->extract_preceding_documentation();
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
+
+  # my $entity_type = "method";
+
+  # unless ($$self{in_class})
+  # {
+  #   print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
+  #   return;
+  # }
+
+  # my $objCfunc;
+  # my $objCppfunc;
+
+  # # handle first argument
+  # my $argCppMethodDecl = $args[0];
+  # if ($argCppMethodDecl !~ m/\S/s)
+  # {
+  #   print STDERR "$filename:$line_num:_WRAP_METHOD: missing prototype\n";
+  #   return;
+  # }
+
+  # #Parse the method decaration and build an object that holds the details:
+  # $objCppfunc = &Function::new($argCppMethodDecl, $self);
+
+  # # handle second argument:
+
+  # my $argCFunctionName = $args[1];
+  # $argCFunctionName = Util::string_trim($argCFunctionName);
+
+  # #Get the c function's details:
+
+  # # Checks that it's not empty and that it contains no whitespace.
+  # if ($argCFunctionName =~ m/^\S+$/s)
+  # {
+  #   #c-name. e.g. gtk_clist_set_column_title
+  #   $objCfunc = GtkDefs::lookup_function($argCFunctionName);
+
+  #   if(!$objCfunc) #If the lookup failed:
+  #   {
+  #     $objOutputter->output_wrap_failed($argCFunctionName, "method defs lookup failed (1)");
+  #     return;
+  #   }
+  # }
+
+  # # Extra stuff needed?
+  # $$objCfunc{rettype_needs_ref} = 0;
+  # $$objCfunc{throw_any_errors} = 0;
+  # $$objCfunc{constversion} = 0;
+  # $$objCfunc{deprecated} = "";
+  # my $deprecation_docs = "";
+  # my $ifdef;
+  # while($#args >= 2) # If the optional ref/err/deprecated arguments are there.
+  # {
+  #   my $argRef = Util::string_trim(pop @args);
+  #   #print "debug arg=$argRef\n";
+  #   if($argRef eq "refreturn")
+  #   {
+  #     $$objCfunc{rettype_needs_ref} = 1;
+  #   }
+  #   elsif($argRef eq "errthrow")
+  #   {
+  #     $$objCfunc{throw_any_errors} = 1;
+  #   }
+  #   elsif($argRef eq "constversion")
+  #   {
+  #     $$objCfunc{constversion} = 1;
+  #   }
+  #   elsif($argRef =~ /^deprecated(.*)/) #If deprecated is at the start.
+  #   {
+  #     $$objCfunc{deprecated} = "deprecated";
+
+  #     if($1 ne "")
+  #     {
+  #       $deprecation_docs = Util::string_unquote(Util::string_trim($1));
+  #     }
+  #   }
+  #   elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+  #   {
+  #     $ifdef = $1;
+  #   }
+  # }
+
+  # if ($commentblock ne '')
+  # {
+  #   $commentblock = '  /**' . $commentblock . "\n   */\n";
+  # }
+  # else
+  # {
+  #   $commentblock = DocsParser::lookup_documentation($argCFunctionName, $deprecation_docs);
+  # }
+
+  # $objOutputter->output_wrap_meth($filename, $line_num, $objCppfunc, $objCfunc, $argCppMethodDecl, $commentblock, $ifdef);
+}
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+# TODO: implement it.
+# void on_wrap_method_docs_only()
+sub on_wrap_method_docs_only($)
+{
+  my ($self) = @_;
 
-  my $commentblock = $self->extract_preceding_documentation();
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  $self->extract_bracketed_text;
+  # my $objOutputter = $$self{objOutputter};
 
-  my $entity_type = "method";
+  # return unless ($self->check_for_eof());
 
-  unless ($$self{in_class})
-    {
-      print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
-      return;
-    }
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
 
-  my $objCfunc;
-  my $objCppfunc;
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
 
-  # handle first argument
-  my $argCppMethodDecl = $args[0];
-  if ($argCppMethodDecl !~ m/\S/s)
-  {
-    print STDERR "$filename:$line_num:_WRAP_METHOD: missing prototype\n";
-    return;
-  }
+  # my $entity_type = "method";
 
-  #Parse the method decaration and build an object that holds the details:
-  $objCppfunc = &Function::new($argCppMethodDecl, $self);
+  # if (!$$self{in_class})
+  #   {
+  #     print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
+  #     return;
+  #   }
 
-  # handle second argument:
+  # my $objCfunc;
 
-  my $argCFunctionName = $args[1];
-  $argCFunctionName = Util::string_trim($argCFunctionName);
+  # # handle first argument
+  # my $argCFunctionName = $args[0];
+  # $argCFunctionName = Util::string_trim($argCFunctionName);
 
-  #Get the c function's details:
+  # # Get the C function's details:
 
-  # Checks that it's not empty and that it contains no whitespace.
-  if ($argCFunctionName =~ m/^\S+$/s)
-  {
-    #c-name. e.g. gtk_clist_set_column_title
-    $objCfunc = GtkDefs::lookup_function($argCFunctionName);
+  # # Checks that it's not empty or contains whitespace
+  # if ($argCFunctionName =~ m/^\S+$/s)
+  # {
+  #   #c-name. e.g. gtk_clist_set_column_title
+  #   $objCfunc = GtkDefs::lookup_function($argCFunctionName);
 
-    if(!$objCfunc) #If the lookup failed:
-    {
-      $objOutputter->output_wrap_failed($argCFunctionName, "method defs lookup failed (1)");
-      return;
-    }
-  }
+  #   if(!$objCfunc) #If the lookup failed:
+  #   {
+  #     $objOutputter->output_wrap_failed($argCFunctionName, "method defs lookup failed (1)");
+  #     return;
+  #   }
+  # }
 
-  # Extra stuff needed?
-  $$objCfunc{rettype_needs_ref} = 0;
-  $$objCfunc{throw_any_errors} = 0;
-  $$objCfunc{constversion} = 0;
-  $$objCfunc{deprecated} = "";
-  my $deprecation_docs = "";
-  my $ifdef;
-  while($#args >= 2) # If the optional ref/err/deprecated arguments are there.
-  {
-    my $argRef = Util::string_trim(pop @args);
-    #print "debug arg=$argRef\n";
-    if($argRef eq "refreturn")
-    {
-      $$objCfunc{rettype_needs_ref} = 1;
-    }
-    elsif($argRef eq "errthrow")
-    {
-      $$objCfunc{throw_any_errors} = 1;
-    }
-    elsif($argRef eq "constversion")
-    {
-      $$objCfunc{constversion} = 1;
-    }
-    elsif($argRef =~ /^deprecated(.*)/) #If deprecated is at the start.
-    {
-      $$objCfunc{deprecated} = "deprecated";
+  # # Extra ref needed?
+  # $$objCfunc{throw_any_errors} = 0;
+  # while($#args >= 1) # If the optional ref/err arguments are there.
+  # {
+  #   my $argRef = Util::string_trim(pop @args);
+  #   if($argRef eq "errthrow")
+  #   {
+  #     $$objCfunc{throw_any_errors} = 1;
+  #   }
+  # }
 
-      if($1 ne "")
-      {
-        $deprecation_docs = Util::string_unquote(Util::string_trim($1));
-      }
-    }
-    elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
-    {
-      $ifdef = $1;
-    }
-  }
+  # my $commentblock = "";
+  # $commentblock = DocsParser::lookup_documentation($argCFunctionName, "");
 
-  if ($commentblock ne '')
-  {
-    $commentblock = '  /**' . $commentblock . "\n   */\n";
-  }
-  else
-  {
-    $commentblock = DocsParser::lookup_documentation($argCFunctionName, $deprecation_docs);
-  }
-
-  $objOutputter->output_wrap_meth($filename, $line_num, $objCppfunc, $objCfunc, $argCppMethodDecl, $commentblock, $ifdef);
+  # $objOutputter->output_wrap_meth_docs_only($filename, $line_num, $commentblock);
 }
 
-# void on_wrap_method_docs_only()
-sub on_wrap_method_docs_only($)
+# TODO: implement it.
+sub on_wrap_ctor($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
 
-  return unless ($self->check_for_eof());
+  $self->extract_bracketed_text;
+  # my $objOutputter = $$self{objOutputter};
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+  # if( !($self->check_for_eof()) )
+  # {
+  #  return;
+  # }
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
 
-  my $entity_type = "method";
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
 
-  if (!$$self{in_class})
-    {
-      print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
-      return;
-    }
+  # my $entity_type = "method";
 
-  my $objCfunc;
+  # if (!$$self{in_class})
+  #   {
+  #     print STDERR "$filename:$line_num:_WRAP_CTOR macro encountered outside class\n";
+  #     return;
+  #   }
 
-  # handle first argument
-  my $argCFunctionName = $args[0];
-  $argCFunctionName = Util::string_trim($argCFunctionName);
+  # my $objCfunc;
+  # my $objCppfunc;
 
-  # Get the C function's details:
+  # # handle first argument
+  # my $argCppMethodDecl = $args[0];
+  # if ($argCppMethodDecl !~ m/\S/s)
+  #   {
+  #     print STDERR "$filename:$line_num:_WRAP_CTOR: missing prototype\n";
+  #     return;
+  #   }
 
-  # Checks that it's not empty or contains whitespace
-  if ($argCFunctionName =~ m/^\S+$/s)
-  {
-    #c-name. e.g. gtk_clist_set_column_title
-    $objCfunc = GtkDefs::lookup_function($argCFunctionName);
+  # #Parse the method decaration and build an object that holds the details:
+  # $objCppfunc = &Function::new_ctor($argCppMethodDecl, $self);
 
-    if(!$objCfunc) #If the lookup failed:
-    {
-      $objOutputter->output_wrap_failed($argCFunctionName, "method defs lookup failed (1)");
-      return;
-    }
-  }
+  # # handle second argument:
 
-  # Extra ref needed?
-  $$objCfunc{throw_any_errors} = 0;
-  while($#args >= 1) # If the optional ref/err arguments are there.
-  {
-    my $argRef = Util::string_trim(pop @args);
-    if($argRef eq "errthrow")
-    {
-      $$objCfunc{throw_any_errors} = 1;
-    }
-  }
+  # my $argCFunctionName = $args[1];
+  # $argCFunctionName = Util::string_trim($argCFunctionName);
 
-  my $commentblock = "";
-  $commentblock = DocsParser::lookup_documentation($argCFunctionName, "");
+  # #Get the C function's details:
+  # if ($argCFunctionName =~ m/^\S+$/s)
+  # {
+  #   $objCfunc = GtkDefs::lookup_function($argCFunctionName); #c-name. e.g. gtk_clist_set_column_title
+  #   if(!$objCfunc) #If the lookup failed:
+  #   {
+  #     $objOutputter->output_wrap_failed($argCFunctionName, "ctor defs lookup failed (2)");
+  #     return;
+  #   }
+  # }
 
-  $objOutputter->output_wrap_meth_docs_only($filename, $line_num, $commentblock);
+  # $objOutputter->output_wrap_ctor($filename, $line_num, $objCppfunc, $objCfunc, $argCppMethodDecl);
 }
 
-sub on_wrap_ctor($)
+# TODO: implement it.
+sub on_implements_interface ($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
 
-  if( !($self->check_for_eof()) )
-  {
-   return;
-  }
+  $self->extract_bracketed_text;
+  # if( !($self->check_for_eof()) )
+  # {
+  #  return;
+  # }
+
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
+
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
+
+  # # handle first argument
+  # my $interface = $args[0];
+
+  # # Extra stuff needed?
+  # my $ifdef;
+  # while($#args >= 1) # If the optional ref/err/deprecated arguments are there.
+  # {
+  #   my $argRef = Util::string_trim(pop @args);
+  #   if($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+  #   {
+  #     $ifdef = $1;
+  #   }
+  # }
+  # my $objOutputter = $$self{objOutputter};
+  # $objOutputter->output_implements_interface($interface, $ifdef);
+}
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+# TODO: implement it.
+sub on_wrap_create($)
+{
+  my ($self) = @_;
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  $self->extract_bracketed_text;
 
-  my $entity_type = "method";
+  # if( !($self->check_for_eof()) )
+  # {
+  #   return;
+  # }
 
-  if (!$$self{in_class})
-    {
-      print STDERR "$filename:$line_num:_WRAP_CTOR macro encountered outside class\n";
-      return;
-    }
+  # my $str = $self->extract_bracketed_text();
 
-  my $objCfunc;
-  my $objCppfunc;
+  # my $objOutputter = $$self{objOutputter};
+  # $objOutputter->output_wrap_create($str, $self);
+}
 
-  # handle first argument
-  my $argCppMethodDecl = $args[0];
-  if ($argCppMethodDecl !~ m/\S/s)
-    {
-      print STDERR "$filename:$line_num:_WRAP_CTOR: missing prototype\n";
-      return;
-    }
+# TODO: split the common part from it and make two methods with merging doxycomment and without it. Implement it actually.
+sub on_wrap_signal($)
+{
+  my ($self) = @_;
 
-  #Parse the method decaration and build an object that holds the details:
-  $objCppfunc = &Function::new_ctor($argCppMethodDecl, $self);
+  $self->extract_bracketed_text;
+  # my ($self, $merge_doxycomment_with_previous) = @_;
+
+  # if( !($self->check_for_eof()) )
+  # {
+  #   return;
+  # }
+
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
+
+  # #Get the arguments:
+  # my $argCppDecl = $args[0];
+  # my $argCName = $args[1];
+  # $argCName = Util::string_trim($argCName);
+  # $argCName = Util::string_unquote($argCName);
+
+  # my $bCustomDefaultHandler = 0;
+  # my $bNoDefaultHandler = 0;
+  # my $bCustomCCallback = 0;
+  # my $bRefreturn = 0;
+  # my $ifdef;
+
+  # while($#args >= 2) # If optional arguments are there.
+  # {
+  #   my $argRef = Util::string_trim(pop @args);
+  #   if($argRef eq "custom_default_handler")
+  #   {
+  #     $bCustomDefaultHandler = 1;
+  #   }
+
+  #   if($argRef eq "no_default_handler")
+  #   {
+  #     $bNoDefaultHandler = 1;
+  #   }
+
+  #   if($argRef eq "custom_c_callback")
+  #   {
+  #     $bCustomCCallback = 1;
+  #   }
+
+  #   if($argRef eq "refreturn")
+  #   {
+  #     $bRefreturn = 1;
+  #   }
+
+  #   elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+  #   {
+  #     $ifdef = $1;
+  #   }
+  # }
+
+  # $self->output_wrap_signal($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
+  #                           $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback,
+  #                           $bRefreturn, $ifdef, $merge_doxycomment_with_previous);
+}
 
-  # handle second argument:
+# TODO: implement it.
+# void on_wrap_vfunc()
+sub on_wrap_vfunc($)
+{
+  my ($self) = @_;
 
-  my $argCFunctionName = $args[1];
-  $argCFunctionName = Util::string_trim($argCFunctionName);
+  $self->extract_bracketed_text;
+
+  # if( !($self->check_for_eof()) )
+  # {
+  #   return;
+  # }
+
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
+
+  # #Get the arguments:
+  # my $argCppDecl = $args[0];
+  # my $argCName = $args[1];
+  # $argCName = Util::string_trim($argCName);
+  # $argCName = Util::string_unquote($argCName);
+
+  # my $refreturn = 0;
+  # my $refreturn_ctype = 0;
+  # my $custom_vfunc = 0;
+  # my $custom_vfunc_callback = 0;
+  # my $ifdef = "";
+
+  # while($#args >= 2) # If optional arguments are there.
+  # {
+  #   my $argRef = Util::string_trim(pop @args);
+
+  #   # Extra ref needed?
+  #   if($argRef eq "refreturn")
+  #   {
+  #     $refreturn = 1;
+  #   }
+  #   elsif($argRef eq "refreturn_ctype")
+  #   {
+  #     $refreturn_ctype = 1;
+  #   }
+  #   elsif($argRef eq "custom_vfunc")
+  #   {
+  #     $custom_vfunc = 1;
+  #   }
+  #   elsif($argRef eq "custom_vfunc_callback")
+  #   {
+  #     $custom_vfunc_callback = 1;
+  #   }
+  #   elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+  #   {
+  #     $ifdef = $1;
+  #   }
+  # }
+
+  # $self->output_wrap_vfunc($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
+  #                          $refreturn, $refreturn_ctype, $custom_vfunc,
+  #                          $custom_vfunc_callback, $ifdef);
+}
+
+sub extract_members ($$)
+{
+  my ($object, $substs) = @_;
+  my $member_count = $object->get_g_member_count;
+  my @all_members = ();
 
-  #Get the C function's details:
-  if ($argCFunctionName =~ m/^\S+$/s)
+  for (my $iter = 0; $iter < $member_count; ++$iter)
   {
-    $objCfunc = GtkDefs::lookup_function($argCFunctionName); #c-name. e.g. gtk_clist_set_column_title
-    if(!$objCfunc) #If the lookup failed:
+    my $member = $object->get_g_member_by_index ($iter);
+    my $name = uc $member->get_a_name;
+    my $value = $member->get_a_value;
+
+    foreach my $pair (@{$substs})
     {
-      $objOutputter->output_wrap_failed($argCFunctionName, "ctor defs lookup failed (2)");
-      return;
+      $name =~ s#$pair->[0]#$pair->[1]#;
+      $value =~ s#$pair->[0]#$pair->[1]#;
     }
+    push @all_members, [$name, $value];
   }
 
-  $objOutputter->output_wrap_ctor($filename, $line_num, $objCppfunc, $objCfunc, $argCppMethodDecl);
+  return \ all_members;
 }
 
-sub on_implements_interface($$)
+#TODO: implement beautifying if I am really bored.
+sub convert_members_to_strings($)
 {
-  my ($self) = @_;
+  my ($members) = @_;
+  my @strings = ();
 
-  if( !($self->check_for_eof()) )
+  foreach my $pair (@{$members})
   {
-   return;
+    my $name = $pair->[0];
+    my $value = $pair->[1];
+
+    push @strings, '    ' . $name . ' = ' . $value;
   }
+  return \ strings;
+}
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+sub on_wrap_enum($)
+{
+  my ($self) = @_;
+  my $repositories = $self->{'repositories'};
+  my $module = $self->{'module'};
+  my $repository = $repositories->get_repository ($module);
+  my $namespace = $repository->get_g_namespace_by_name ($module);
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  return unless $self->check_for_eof;
 
-  # handle first argument
-  my $interface = $args[0];
+  # get the arguments
+  my @args = string_split_commas ($self->extract_bracketed_text);
+  my $cpp_type = Util::string_trim(shift @args);
+  my $c_enum = Util::string_trim(shift @args);
+  my $flags = 0;
+  my $enum = $namespace->get_g_enumeration_by_name ($c_enum);
 
-  # Extra stuff needed?
-  my $ifdef;
-  while($#args >= 1) # If the optional ref/err/deprecated arguments are there.
+  unless (defined $enum)
   {
-    my $argRef = Util::string_trim(pop @args);
-    if($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+    $enum = $namespace->get_g_bitfield_by_name ($c_enum);
+    $flags = 1;
+    unless (defined $enum)
     {
-      $ifdef = $1;
+      $self->error ('No enum or flags `' . $c_enum . '\' found.');
     }
   }
-  my $objOutputter = $$self{objOutputter};
-  $objOutputter->output_implements_interface($interface, $ifdef);
-}
 
-sub on_wrap_create($)
-{
-  my ($self) = @_;
+  my @substs = ();
 
-  if( !($self->check_for_eof()) )
+  if (@args)
   {
-    return;
+    foreach my $arg (@args)
+    {
+      if ($arg eq 'NO_GTYPE')
+      {
+        $self->warning ('NO_GTYPE parameter is deprecated.');
+      }
+      elsif ($arg =~ /^\s*s#([^#]+)#([^#]*)#\s*$/)
+      {
+        push @substs, [$1, $2];
+      }
+      elsif (/^\s*get_type_func=.*$/)
+      {
+        $self->warning ('get-type-func parameter is deprecated.');
+      }
+      else
+      {
+        $self->warning ('Unknown parameter passed to _WRAP_GERROR: `' . $arg . '\'.');
+      }
+    }
   }
 
-  my $str = $self->extract_bracketed_text();
-
-  my $objOutputter = $$self{objOutputter};
-  $objOutputter->output_wrap_create($str, $self);
-}
-
-sub on_wrap_signal($$)
-{
-  my ($self, $merge_doxycomment_with_previous) = @_;
-
-  if( !($self->check_for_eof()) )
+  unless (defined $enum)
   {
-    return;
+    $self->error ('No enum `' . $c_enum . '\' found.');
   }
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  my $gir_gtype = $enum->get_a_glib_get_type;
+  my $members = extract_members ($enum, \ substs);
+  my $string_members = convert_members_to_strings ($members);
+  my $code_string = nl ('enum ' . $cpp_type) .
+                    nl ('{') .
+                    nl (join (nl (','), $string_members)) .
+                    nl ('};') .
+                    nl ();
+
+  if ($flags)
+  {
+    $code_string .= nl ('inline ' . $cpp_type . ' operator|(' . $cpp_type . ' lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('  { return static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . ' operator&(' . $cpp_type . ' lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('  { return static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . ' operator^(' . $cpp_type . ' lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('{ return static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs)); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . ' operator~(' . $cpp_type . ' flags)') .
+                    nl ('  { return static_cast<' . $cpp_type . '>(~static_cast<unsigned>(flags)); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . '& operator|=(' . $cpp_type . '& lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('  { return (lhs = static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs))); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . '& operator&=(' . $cpp_type . '& lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('  { return (lhs = static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs))); }') .
+                    nl () .
+                    nl ('inline ' . $cpp_type . '& operator^=(' . $cpp_type . '& lhs, ' . $cpp_type . ' rhs)') .
+                    nl ('  { return (lhs = static_cast<' . $cpp_type . '>(static_cast<unsigned>(lhs) ^ static_cast<unsigned>(rhs))); }') .
+                    nl ();
 
-  #Get the arguments:
-  my $argCppDecl = $args[0];
-  my $argCName = $args[1];
-  $argCName = Util::string_trim($argCName);
-  $argCName = Util::string_unquote($argCName);
+  }
 
-  my $bCustomDefaultHandler = 0;
-  my $bNoDefaultHandler = 0;
-  my $bCustomCCallback = 0;
-  my $bRefreturn = 0;
-  my $ifdef;
+  my $namespaces = $self->{'namespace'};
+  my $error_namespaces = $self->join_namespaces;
+  my $full_cpp_type = join ('::', $error_namespaces, $cpp_type);
 
-  while($#args >= 2) # If optional arguments are there.
+  if (defined $gir_gtype)
   {
-    my $argRef = Util::string_trim(pop @args);
-    if($argRef eq "custom_default_handler")
+    my $close = 1;
+
+    if (@{$namespaces} == 1 and $namespaces->[0] eq 'Glib')
     {
-      $bCustomDefaultHandler = 1;
+      $close = 0;
     }
 
-    if($argRef eq "no_default_handler")
+    if ($close)
     {
-      $bNoDefaultHandler = 1;
+      $code_string .= Common::Output::Shared::close_namespaces $self->get_namespaces;
     }
 
-    if($argRef eq "custom_c_callback")
+    my $value_base = 'Glib::Value_';
+
+    if ($flags)
     {
-      $bCustomCCallback = 1;
+      $value_base .= 'Flags';
     }
-
-    if($argRef eq "refreturn")
+    else
     {
-      $bRefreturn = 1;
+      $value_base .= 'Enum';
     }
-
-    elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+    $code_string .= nl (Common::Output::Shared::doxy_skip_begin) .
+                    nl ('namespace Glib') .
+                    nl ('{') .
+                    nl () .
+                    nl ('template <>') .
+                    nl ('class Value< ' . $full_cpp_type . ' > : public ' . $value_base . '< ' . $full_cpp_type . '> ') .
+                    nl ('{') .
+                    nl ('public:') .
+                    nl ('  static GType value_type() G_GNUC_CONST;') .
+                    nl ('};') .
+                    nl () .
+                    nl ('} // namespace Glib') .
+                    nl (Common::Output::Shared::doxy_skip_end) .
+                    nl ();
+
+    if ($close)
     {
-      $ifdef = $1;
+      $code_string .= Common::Output::Shared::open_namespaces $self->get_namespaces;
     }
   }
 
-  $self->output_wrap_signal($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
-                            $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback,
-                            $bRefreturn, $ifdef, $merge_doxycomment_with_previous);
-}
+  my $section_manager = $self->{'section_manager'};
 
-# void on_wrap_vfunc()
-sub on_wrap_vfunc($)
-{
-  my ($self) = @_;
+  $section_manager->append_string_to_section ($code_string, Common::SectionManager::SECTION_H);
 
-  if( !($self->check_for_eof()) )
+  if (defined $gir_gtype)
   {
-    return;
+    $code_string = nl ('// static') .
+                   nl ('GType Glib::Value< ' . $full_cpp_type . ' >::value_type()') .
+                   nl ('{') .
+                   nl ('  return ' . $gir_gtype . '();') .
+                   nl ('}') .
+                   nl ();
+    $section_manager->append_string_to_section ($code_string, 'SECTION_CCG_END');
   }
+}
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+sub on_wrap_gerror ($)
+{
+  my ($self) = @_;
+  my $repositories = $self->{'repositories'};
+  my $module = $self->{'module'};
+  my $repository = $repositories->get_repository ($module);
+  my $namespace = $repository->get_g_namespace_by_name ($module);
 
-  #Get the arguments:
-  my $argCppDecl = $args[0];
-  my $argCName = $args[1];
-  $argCName = Util::string_trim($argCName);
-  $argCName = Util::string_unquote($argCName);
+  return unless $self->check_for_eof;
 
-  my $refreturn = 0;
-  my $refreturn_ctype = 0;
-  my $custom_vfunc = 0;
-  my $custom_vfunc_callback = 0;
-  my $ifdef = "";
+  # get the arguments
+  my @args = string_split_commas ($self->extract_bracketed_text);
+  my $cpp_type = Util::string_trim(shift @args);
+  my $c_enum = Util::string_trim(shift @args);
+  my $enum = $namespace->get_g_enumeration_by_name ($c_enum);
+  my @substs = ();
 
-  while($#args >= 2) # If optional arguments are there.
+  if (@args)
   {
-    my $argRef = Util::string_trim(pop @args);
+    my $first_iteration = 1;
 
-    # Extra ref needed?
-    if($argRef eq "refreturn")
-    {
-      $refreturn = 1;
-    }
-    elsif($argRef eq "refreturn_ctype")
+    foreach my $arg (@args)
     {
-      $refreturn_ctype = 1;
+      if ($arg eq 'NO_GTYPE')
+      {
+        $self->warning ('NO_GTYPE parameter is deprecated.');
+      }
+      elsif ($arg =~ /^\s*s#([^#]+)#([^#]*)#\s*$/)
+      {
+        push @substs, [$1, $2];
+      }
+      elsif (/^\s*get_type_func=.*$/)
+      {
+        $self->warning ('get-type-func parameter is deprecated.');
+      }
+      elsif ($first_iteration)
+      {
+        $self->warning ('Domain parameter is deprecated.');
+      }
+      else
+      {
+        $self->warning ('Unknown parameter passed to _WRAP_GERROR: `' . $arg . '\'.');
+      }
+      $first_iteration = 0;
     }
-    elsif($argRef eq "custom_vfunc")
+  }
+
+  unless (defined $enum)
+  {
+    $self->error ('No enum `' . $c_enum . '\' found.');
+  }
+
+  my $gir_gtype = $enum->get_a_glib_get_type;
+  my $gir_domain = $enum->get_a_glib_error_domain;
+  my $members = extract_members ($enum, \ substs);
+  my $string_members = convert_members_to_strings ($members);
+  my $code_string = nl ('class ' . $cpp_type . ' : public Glib:error') .
+                    nl ('{') .
+                    nl ('public:') .
+                    nl ('  enum Code') .
+                    nl ('  {') .
+                    nl (join nl (','), @{$string_members}) .
+                    nl ('  };') .
+                    nl () .
+                    nl ('  ' . $cpp_type . '(Code error_code, const Glib::ustring& error_message);') .
+                    nl ('  explicit ' . $cpp_type . '(GError* gobject);') .
+                    nl ('  Code code() const;') .
+                    nl () .
+                    nl (Common::Output::Shared::doxy_skip_begin) .
+                    nl ('private:') .
+                    nl () .
+                    nl ('  static void throw_func(GError* gobject);') .
+                    nl () .
+                    nl ('  friend void wrap_init(); // uses throw_func()') .
+                    nl (Common::Output::Shared::doxy_skip_end) .
+                    nl ('};') .
+                    nl ();
+
+  my $error_namespaces = $self->join_namespaces;
+  my $full_cpp_type = join ('::', $error_namespaces, $cpp_type);
+
+  if (defined $gir_gtype)
+  {
+    my $namespaces = $self->{'namespace'};
+    my $close = 1;
+    if (@{$namespaces} == 1 and $namespaces->[0] eq 'Glib')
     {
-      $custom_vfunc = 1;
+      $close = 0;
     }
-    elsif($argRef eq "custom_vfunc_callback")
+
+    if ($close)
     {
-      $custom_vfunc_callback = 1;
+      $code_string .= Common::Output::Shared::close_namespaces $self->get_namespaces;
     }
-    elsif($argRef =~ /^ifdef(.*)/) #If ifdef is at the start.
+
+    $code_string .= nl (Common::Output::Shared::doxy_skip_begin) .
+                    nl ('namespace Glib') .
+                    nl ('{') .
+                    nl () .
+                    nl ('template <>') .
+                    nl ('class Value< ' . $full_cpp_type . '::Code > : public Glib::Value_Enum< ' . $full_cpp_type . '::Code >') .
+                    nl ('{') .
+                    nl ('public:') .
+                    nl ('  static GType value_type() G_GNUC_CONST;') .
+                    nl ('};') .
+                    nl () .
+                    nl ('} // namespace Glib') .
+                    nl (Common::Output::Shared::doxy_skip_end) .
+                    nl ();
+
+    if ($close)
     {
-      $ifdef = $1;
+      $code_string .= Common::Output::Shared::open_namespaces $self->get_namespaces;
     }
   }
 
-  $self->output_wrap_vfunc($argCppDecl, $argCName, $$self{filename}, $$self{line_num},
-                           $refreturn, $refreturn_ctype, $custom_vfunc,
-                           $custom_vfunc_callback, $ifdef);
+  my $section_manager = $self->{'section_manager'};
+
+  $section_manager->append_string_to_section ($code_string, Common::SectionManager::SECTION_H);
+  $code_string = nl ($full_cpp_type . '::' . $cpp_type . '(' . $full_cpp_type . '::Code error_code, const Glib::ustring& error_message)') .
+                 nl (':') .
+                 nl ('  Glib::Error(g_quark_from_static_string ("' . $gir_domain . '"), error_code, error_message)') .
+                 nl ('{}') .
+                 nl () .
+                 nl ($full_cpp_type . '::' . $cpp_type . '(GError* gobject)') .
+                 nl (':') .
+                 nl ('  Glib::Error(gobject)') .
+                 nl ('{}') .
+                 nl () .
+                 nl ($full_cpp_type . '::Code ' . $full_cpp_type . '::code() const') .
+                 nl ('{') .
+                 nl ('  return static_cast<Code>(Glib::Error::code());') .
+                 nl ('}') .
+                 nl () .
+                 nl ('// static') .
+                 nl ('void ' . $full_cpp_type . '::throw_func(GError* gobject)') .
+                 nl ('{') .
+                 nl ('  throw ' . $full_cpp_type . '(gobject);') .
+                 nl ('}') .
+                 nl ();
+
+  if (defined $gir_gtype)
+  {
+    $code_string .= nl ('// static') .
+                    nl ('GType Glib::Value< ' . $full_cpp_type . '::Code >::value_type()') .
+                    nl ('{') .
+                    nl ('  return ' . $gir_gtype . '();') .
+                    nl ('}') .
+                    nl ();
+  }
+
+  $section_manager->append_string_to_section ($code_string, 'SECTION_CCG_END');
 }
 
-sub on_wrap_enum($)
+# TODO: implement it.
+sub on_wrap_property($)
 {
   my ($self) = @_;
 
-  return unless ($self->check_for_eof());
+  $self->extract_bracketed_text;
+  # my $objOutputter = $$self{objOutputter};
 
-  my $outputter = $$self{objOutputter};
-  my $comment = $self->extract_preceding_documentation();
+  # return unless ($self->check_for_eof());
 
-  # get the arguments
-  my @args = string_split_commas($self->extract_bracketed_text());
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
 
-  my $cpp_type = Util::string_trim(shift(@args));
-  my $c_type   = Util::string_trim(shift(@args));
+  # #Get the arguments:
+  # my $argPropertyName = $args[0];
+  # $argPropertyName = Util::string_trim($argPropertyName);
+  # $argPropertyName = Util::string_unquote($argPropertyName);
 
-  # The remaining elements in @args could be flags or s#^FOO_## substitutions.
+  # #Convert the property name to a canonical form, as it is inside gobject.
+  # #Otherwise, gobject might not recognise the name,
+  # #and we will not recognise the property name when we get notification that the value changes.
+  # $argPropertyName =~ tr/_/-/;
 
-  $outputter->output_wrap_enum(
-      $$self{filename}, $$self{line_num}, $cpp_type, $c_type, $comment, @args);
+  # my $argCppType = $args[1];
+  # $argCppType = Util::string_trim($argCppType);
+  # $argCppType = Util::string_unquote($argCppType);
+
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
+
+  # $objOutputter->output_wrap_property($filename, $line_num, $argPropertyName, $argCppType, $$self{c_class});
 }
 
-sub on_wrap_gerror($)
+# TODO: either remove it or make use of it in every _WRAP macro specific for class.
+sub output_wrap_check($$$$$$)
 {
-  my ($self) = @_;
+  my ($self, $CppDecl, $signal_name, $filename, $line_num, $macro_name) = @_;
 
-  return unless ($self->check_for_eof());
+  #Some checks:
 
-  # get the arguments
-  my @args = string_split_commas($self->extract_bracketed_text());
+  unless ($self->{'in_class'})
+  {
+    $self->error ($macro_name . 'macro encountered outside class');
+  }
+  if ($CppDecl !~ m/\S/s)
+  {
+    $self->error ($macro_name . ': missing prototype');
+  }
+  return 0;
+}
 
-  my $cpp_type = Util::string_trim(shift(@args));
-  my $c_enum   = Util::string_trim(shift(@args));
-  my $domain   = Util::string_trim(shift(@args));
+# TODO: we probably won't need this.
+# void output_wrap($CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, $bRefreturn)
+# sub output_wrap_signal($$$$$$$$$)
+# {
+#   my ($self, $CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, $bRefreturn, $ifdef, $merge_doxycomment_with_previous) = @_;
 
-  # The remaining elements in @args could be flags or s#^FOO_## substitutions.
+#   #Some checks:
+#   return if ($self->output_wrap_check($CppDecl, $signal_name,
+#                                       $filename, $line_num, "_WRAP_SIGNAL"));
+#   # handle first argument
 
-  $$self{objOutputter}->output_wrap_gerror(
-      $$self{filename}, $$self{line_num}, $cpp_type, $c_enum, $domain, @args);
-}
+#   #Parse the method declaration and build an object that holds the details:
+#   my $objCppSignal = &Function::new($CppDecl, $self);
+#   $$objCppSignal{class} = $$self{class}; #Remember the class name for use in Outputter::output_wrap_signal().
 
-sub on_wrap_property($)
+
+#   # handle second argument:
+#   my $objCSignal = undef;
+
+#   my $objOutputter = $$self{objOutputter};
+
+#   #Get the c function's details:
+#   if ($signal_name ne '')
+#   {
+#     $objCSignal = GtkDefs::lookup_signal($$self{c_class}, $signal_name);
+
+#     # Check for failed lookup.
+#     if($objCSignal eq 0)
+#     {
+#     print STDERR "$signal_name\n";
+#       $objOutputter->output_wrap_failed($signal_name,
+#         " signal defs lookup failed");
+#       return;
+#     }
+#   }
+
+#   $objOutputter->output_wrap_sig_decl($filename, $line_num, $objCSignal, $objCppSignal, $signal_name, $bCustomCCallback, $ifdef, $merge_doxycomment_with_previous);
+
+#   if($bNoDefaultHandler eq 0)
+#   {
+#     $objOutputter->output_wrap_default_signal_handler_h($filename, $line_num, $objCppSignal, $objCSignal, $ifdef);
+
+#     my $bImplement = 1;
+#     if($bCustomDefaultHandler) { $bImplement = 0; }
+#     $objOutputter->output_wrap_default_signal_handler_cc($filename, $line_num, $objCppSignal, $objCSignal, $bImplement, $bCustomCCallback, $bRefreturn, $ifdef);
+#   }
+# }
+
+# TODO: we probably won't need this.
+# void output_wrap($CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
+#                  $custom_vfunc, $custom_vfunc_callback, $ifdef)
+# sub output_wrap_vfunc($$$$$$$$)
+# {
+#   my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
+#       $custom_vfunc, $custom_vfunc_callback, $ifdef) = @_;
+
+#   #Some checks:
+#   return if ($self->output_wrap_check($CppDecl, $vfunc_name, $filename, $line_num, '_WRAP_VFUNC'));
+
+#   # handle first argument
+
+#   #Parse the method declaration and build an object that holds the details:
+#   my $objCppVfunc = &Function::new($CppDecl, $self);
+
+
+#   # handle second argument:
+#   my $objCVfunc = undef;
+
+#   my $objOutputter = $$self{objOutputter};
+
+#   #Get the c function's details:
+#   if ($vfunc_name =~ m/^\S+$/s) # if it's not empty and contains no whitespace
+#   {
+#     $objCVfunc = GtkDefs::lookup_signal($$self{c_class},$vfunc_name);
+#     if(!$objCVfunc) #If the lookup failed:
+#     {
+#       $objOutputter->output_wrap_failed($vfunc_name, " vfunc defs lookup failed");
+#       return;
+#     }
+#   }
+
+#   # Write out the appropriate macros.
+#   # These macros are defined in vfunc.m4:
+
+#   $$objCppVfunc{rettype_needs_ref} = $refreturn;
+#   $$objCppVfunc{name} .= "_vfunc"; #All vfuncs should have the "_vfunc" suffix, and a separate easily-named invoker method.
+
+#   $$objCVfunc{rettype_needs_ref} = $refreturn_ctype;
+
+#   $objOutputter->output_wrap_vfunc_h($filename, $line_num, $objCppVfunc, $objCVfunc, $ifdef);
+#   $objOutputter->output_wrap_vfunc_cc($filename, $line_num, $objCppVfunc, $objCVfunc,
+#                                       $custom_vfunc, $custom_vfunc_callback, $ifdef);
+# }
+
+# TODO: what it is for? Remove it.
+# give some sort of weights to sorting attibutes
+# sub byattrib()
+# {
+#   my %attrib_value = (
+#      "virtual_impl" ,1,
+#      "virtual_decl" ,2,
+#      # "sig_impl"     ,3,
+#      "sig_decl"     ,4,
+#      "meth"         ,5
+#   );
+
+#   # $a and $b are hidden parameters to a sorting function
+#   return $attrib_value{$b} <=> $attrib_value{$a};
+# }
+
+
+# TODO: probably implement this. I am not sure.
+# void on_wrap_corba_method()
+sub on_wrap_corba_method($)
 {
   my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
 
-  return unless ($self->check_for_eof());
+  $self->extract_bracketed_text;
+  # my $objOutputter = $$self{objOutputter};
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+  # return unless ($self->check_for_eof());
 
-  #Get the arguments:
-  my $argPropertyName = $args[0];
-  $argPropertyName = Util::string_trim($argPropertyName);
-  $argPropertyName = Util::string_unquote($argPropertyName);
+  # my $filename = $$self{filename};
+  # my $line_num = $$self{line_num};
 
-  #Convert the property name to a canonical form, as it is inside gobject.
-  #Otherwise, gobject might not recognise the name,
-  #and we will not recognise the property name when we get notification that the value changes.
-  $argPropertyName =~ tr/_/-/;
+  # my $str = $self->extract_bracketed_text();
+  # my @args = string_split_commas($str);
 
-  my $argCppType = $args[1];
-  $argCppType = Util::string_trim($argCppType);
-  $argCppType = Util::string_unquote($argCppType);
+  # my $entity_type = "method";
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+  # if (!$$self{in_class})
+  #   {
+  #     print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
+  #     return;
+  #   }
 
-  $objOutputter->output_wrap_property($filename, $line_num, $argPropertyName, $argCppType, $$self{c_class});
-}
+  # my $objCppfunc;
 
+  # # handle first argument
+  # my $argCppMethodDecl = $args[0];
+  # if ($argCppMethodDecl !~ m/\S/s)
+  # {
+  #   print STDERR "$filename:$line_num:_WRAP_CORBA_METHOD: missing prototype\n";
+  #   return;
+  # }
 
-sub output_wrap_check($$$$$$)
+  # # Parse the method decaration and build an object that holds the details:
+  # $objCppfunc = &Function::new($argCppMethodDecl, $self);
+  # $objOutputter->output_wrap_corba_method($filename, $line_num, $objCppfunc);
+}
+
+sub on_insert_section ($)
 {
-  my ($self, $CppDecl, $signal_name, $filename, $line_num, $macro_name) = @_;
+  my ($self) = @_;
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
+  my $str = Util::string_trim $self->extract_bracketed_text;
 
-  #Some checks:
+  $section_manager->append_section_to_section ($str, $main_section);
+}
 
-  unless ($$self{in_class})
+sub on_class_generic ($)
+{
+  my ($self) = @_;
+  my @args = string_split_commas $self->extract_bracketed_text;
+
+  if (@args < 2)
   {
-    print STDERR "$filename:$line_num: $macro_name macro encountered outside class\n";
-    return 1;
+    $self->error ('Too few parameters for _CLASS_GENERIC');
   }
-  if ($CppDecl !~ m/\S/s)
+  elsif (@args > 2)
   {
-    print STDERR "$filename:$line_num:$macro_name: missing prototype\n";
-    return 1;
+    $self->warning ('Superfluous parameters in _CLASS_GENERIC will be ignored.');
   }
-  return '';
+
+  my ($cpp_type, $c_type) = @args;
+  my $code_string = nl ('public:') .
+                    nl (Common::Output::Shared::doxy_skip_begin) .
+                    nl ('  typedef ' . $cpp_type . ' CppObjectType;') .
+                    nl ('  typedef ' . $c_type . ' BaseObjectType;') .
+                    nl (Common::Output::Shared::doxy_skip_end) .
+                    nl () .
+                    nl ('private:') .
+                    nl ();
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
+
+  $section_manager->append_string_to_section ($code_string, $main_section);
 }
 
-# void output_wrap($CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, $bRefreturn)
-sub output_wrap_signal($$$$$$$$$)
+sub on_class_gobject ($)
 {
-  my ($self, $CppDecl, $signal_name, $filename, $line_num, $bCustomDefaultHandler, $bNoDefaultHandler, $bCustomCCallback, $bRefreturn, $ifdef, $merge_doxycomment_with_previous) = @_;
-
-  #Some checks:
-  return if ($self->output_wrap_check($CppDecl, $signal_name,
-                                      $filename, $line_num, "_WRAP_SIGNAL"));
-  # handle first argument
+  my ($self) = @_;
+  my $section_manager = $self->{'section_manager'};
+  my $main_section = $self->{'main_section'};
+  my $line_num = $self->{'line_num'};
+  my @args = string_split_commas $self->extract_bracketed_text;
 
-  #Parse the method declaration and build an object that holds the details:
-  my $objCppSignal = &Function::new($CppDecl, $self);
-  $$objCppSignal{class} = $$self{class}; #Remember the class name for use in Outputter::output_wrap_signal().
+  if (@args > 2)
+  {
+    $self->warning_with_loc ($line_num, 'Last ' . @args - 2 . ' parameters are deprecated.');
+  }
 
+  my $repositories = $self->{'repositories'};
+  my $module = $self->{'module'};
+  my $repository = $repositories->get_repository ($module);
 
-  # handle second argument:
-  my $objCSignal = undef;
+  unless (defined $repository)
+  {
+    $self->error_with_loc ($line_num, 'No such repository: ' . $module);
+  }
 
-  my $objOutputter = $$self{objOutputter};
+  my $namespace = $repository->get_g_namespace_by_name ($module);
 
-  #Get the c function's details:
-  if ($signal_name ne '')
+  unless (defined $namespace)
   {
-    $objCSignal = GtkDefs::lookup_signal($$self{c_class}, $signal_name);
-
-    # Check for failed lookup.
-    if($objCSignal eq 0)
-    {
-    print STDERR "$signal_name\n";
-      $objOutputter->output_wrap_failed($signal_name,
-        " signal defs lookup failed");
-      return;
-    }
+    $self->error_with_loc ($line_num, 'No such namespace: ' . $module);
   }
 
-  $objOutputter->output_wrap_sig_decl($filename, $line_num, $objCSignal, $objCppSignal, $signal_name, $bCustomCCallback, $ifdef, $merge_doxycomment_with_previous);
+  my $gir_prefix = $namespace->get_a_c_identifier_prefixes;
+  my ($cpp_type, $c_type) = @_;
+  my $gir_class = $namespace->get_g_class_by_name ($c_type);
 
-  if($bNoDefaultHandler eq 0)
+  unless (defined $gir_class)
   {
-    $objOutputter->output_wrap_default_signal_handler_h($filename, $line_num, $objCppSignal, $objCSignal, $ifdef);
-
-    my $bImplement = 1;
-    if($bCustomDefaultHandler) { $bImplement = 0; }
-    $objOutputter->output_wrap_default_signal_handler_cc($filename, $line_num, $objCppSignal, $objCSignal, $bImplement, $bCustomCCallback, $bRefreturn, $ifdef);
+    $self->error_with_loc ($line_num, 'No such class: ' . $c_type);
   }
-}
 
-# void output_wrap($CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
-#                  $custom_vfunc, $custom_vfunc_callback, $ifdef)
-sub output_wrap_vfunc($$$$$$$$)
-{
-  my ($self, $CppDecl, $vfunc_name, $filename, $line_num, $refreturn, $refreturn_ctype,
-      $custom_vfunc, $custom_vfunc_callback, $ifdef) = @_;
+  my $get_type_func = $gir_class->get_a_glib_get_type;
 
-  #Some checks:
-  return if ($self->output_wrap_check($CppDecl, $vfunc_name, $filename, $line_num, '_WRAP_VFUNC'));
+  unless (defined $get_type_func)
+  {
+    $self->error_with_loc ($line_num, 'Class `' . $c_type . '\' has no get-type function.');
+  }
 
-  # handle first argument
+  my $gir_parent = $gir_class->get_a_parent;
 
-  #Parse the method declaration and build an object that holds the details:
-  my $objCppVfunc = &Function::new($CppDecl, $self);
+  unless (defined $gir_parent)
+  {
+    $self->error_with_loc ($line_num, 'Class `' . $c_type . '\' has no parent (you are not wrapping GObject, are you?).');
+  }
 
+  my $gir_type_struct = $gir_class->get_a_glib_type_struct;
 
-  # handle second argument:
-  my $objCVfunc = undef;
+  unless (defined $gir_type_struct)
+  {
+    $self->error_with_loc ($line_num, 'Class `' . $c_type . '\' has no Class struct.');
+  }
 
-  my $objOutputter = $$self{objOutputter};
+  my $c_type_class = $gir_prefix . $gir_type_struct;
+  my $c_type_parent;
+  my $c_type_parent_class;
 
-  #Get the c function's details:
-  if ($vfunc_name =~ m/^\S+$/s) # if it's not empty and contains no whitespace
+  # if parent is for example Gtk.Widget
+  if ($gir_parent =~ /^([^.]+)\.(.*)/)
   {
-    $objCVfunc = GtkDefs::lookup_signal($$self{c_class},$vfunc_name);
-    if(!$objCVfunc) #If the lookup failed:
+    my $gir_parent_module = $1;
+    my $gir_parent_name = $2;
+    my $parent_repository = $repositories=>get_repository ($gir_parent_module);
+
+    unless (defined $parent_repository)
     {
-      $objOutputter->output_wrap_failed($vfunc_name, " vfunc defs lookup failed");
-      return;
+      $self->error ('No such repository for parent: `' . $gir_parent_module . '\'.');
     }
-  }
 
-  # Write out the appropriate macros.
-  # These macros are defined in vfunc.m4:
+    my $parent_namespace = $parent_repository->get_g_namespace_by_name ($gir_parent_module);
 
-  $$objCppVfunc{rettype_needs_ref} = $refreturn;
-  $$objCppVfunc{name} .= "_vfunc"; #All vfuncs should have the "_vfunc" suffix, and a separate easily-named invoker method.
-
-  $$objCVfunc{rettype_needs_ref} = $refreturn_ctype;
+    unless (defined $parent_namespace)
+    {
+      $self->error ('No such namespace for parent: `' . $gir_parent_module . '\'.');
+    }
 
-  $objOutputter->output_wrap_vfunc_h($filename, $line_num, $objCppVfunc, $objCVfunc, $ifdef);
-  $objOutputter->output_wrap_vfunc_cc($filename, $line_num, $objCppVfunc, $objCVfunc,
-                                      $custom_vfunc, $custom_vfunc_callback, $ifdef);
-}
+    my $gir_parent_c_prefix = $parent_namespace->get_a_c_identifier_prefixes;
 
-# give some sort of weights to sorting attibutes
-sub byattrib()
-{
-  my %attrib_value = (
-     "virtual_impl" ,1,
-     "virtual_decl" ,2,
-     # "sig_impl"     ,3,
-     "sig_decl"     ,4,
-     "meth"         ,5
-  );
-
-  # $a and $b are hidden parameters to a sorting function
-  return $attrib_value{$b} <=> $attrib_value{$a};
-}
+    $c_type_parent = $gir_parent_c_prefix . $gir_parent_name;
 
+    my $gir_parent_class = $parent_namespace->get_g_class_by_name ($c_type_parent);
 
-# void on_wrap_corba_method()
-sub on_wrap_corba_method($)
-{
-  my ($self) = @_;
-  my $objOutputter = $$self{objOutputter};
+    unless (defined $gir_parent_class)
+    {
+      $self->error_with_loc ($line_num, 'No such parent class in namespace: `' . $c_type_parent . '\.');
+    }
 
-  return unless ($self->check_for_eof());
+    my $gir_parent_type_struct = $gir_parent_class->get_a_glib_type_struct;
 
-  my $filename = $$self{filename};
-  my $line_num = $$self{line_num};
+    unless (defined $gir_parent_type_struct)
+    {
+      $self->error_with_loc ($line_num, 'Parent of `' . $c_type . '\', `' . $c_type_parent . '\' has not Class struct.');
+    }
 
-  my $str = $self->extract_bracketed_text();
-  my @args = string_split_commas($str);
+    $c_type_parent_class = $gir_parent_c_prefix . $gir_parent_type_struct;
+  }
+  else
+  {
+    $c_type_parent = $gir_prefix . $gir_parent;
 
-  my $entity_type = "method";
+    my $gir_parent_class = $namespace->get_g_class_by_name ($c_type_parent);
 
-  if (!$$self{in_class})
+    unless (defined $gir_parent_class)
     {
-      print STDERR "$filename:$line_num:_WRAP macro encountered outside class\n";
-      return;
+      $self->error_with_loc ($line_num, 'No such parent class in namespace: `' . $c_type_parent . '\.');
     }
 
-  my $objCppfunc;
+    my $gir_parent_type_struct = $gir_parent_class->get_a_glib_type_struct;
 
-  # handle first argument
-  my $argCppMethodDecl = $args[0];
-  if ($argCppMethodDecl !~ m/\S/s)
-  {
-    print STDERR "$filename:$line_num:_WRAP_CORBA_METHOD: missing prototype\n";
-    return;
+    unless (defined $gir_parent_type_struct)
+    {
+      $self->error_with_loc ($line_num, 'Parent of `' . $c_type . '\', `' . $c_type_parent . '\' has not Class struct.');
+    }
+
+    $c_type_parent_class = $gir_prefix . $gir_parent_type_struct;
   }
 
-  # Parse the method decaration and build an object that holds the details:
-  $objCppfunc = &Function::new($argCppMethodDecl, $self);
-  $objOutputter->output_wrap_corba_method($filename, $line_num, $objCppfunc);
+  # TODO: write C <-> C++ name store.
+  my $c_cpp_converter = $self->get_c_cpp_converter;
+  my $cpp_type_parent = $c_cpp_converter->from_c_to_cpp ($c_type_parent);
+
+  Common::Output::Gobject::output ($self,
+                                   $c_type,
+                                   $c_type_class,
+                                   $c_type_parent,
+                                   $c_type_parent_class,
+                                   $get_type_func,
+                                   $cpp_type,
+                                   $cpp_type_parent);
 }
 
-
 1; # indicate proper module load.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]