<?xml version="1.0"?>

<!--
 This file is part of GMetaDOM
 a generic bind package for the Document Object Model API.
 Copyright (C) 2001-2002 Luca Padovani <luca.padovani@cs.unibo.it>
               2002 Claudio Sacerdoti Coen <sacerdot@cs.unibo.it>
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 For more information, please visit the project home page
 http://gmetadom.sourceforge.net
 or send an email to <luca.padovani@cs.unibo.it>
-->

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:import href="xslutils.xsl"/>

<xsl:output method="text"/>
<xsl:param name="module" select="'Core'"/>
<xsl:param name="uriprefix" select="''"/>
<xsl:param name="annotations" select="''"/>

<xsl:template match="interface">
<xsl:variable name="prefix">
  <xsl:call-template name="gdomePrefixOfType">
    <xsl:with-param name="type" select="@name"/>
  </xsl:call-template>
</xsl:variable>
/* This file is part of GMetaDOM
 * a generic bind package for the Document Object Model API.
 * Copyright (C) 2001-2002 Luca Padovani &lt;luca.padovani@cs.unibo.it&gt;
 *               2002 Claudio Sacerdoti Coen &lt;sacerdot@cs.unibo.it&gt;
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * For more information, please visit the project home page
 * http://gmetadom.sourceforge.net
 * or send an email to &lt;luca.padovani@cs.unibo.it&gt;
 *
 * DO NOT EDIT: this file has been generated automatically by GMetaDOM
 */

#include &lt;assert.h&gt;
#include &lt;gdome.h&gt;
<xsl:if test="$module = 'Events'">
#include &lt;gdome-events.h&gt;
</xsl:if>
#include &lt;caml/memory.h&gt;
#include &lt;caml/custom.h&gt;
#include "mlgdomevalue.h"

static void
ml_gdome_<xsl:value-of select="$prefix"/>_finalize(value v)
{
  GdomeException exc_;
  Gdome<xsl:value-of select="@name"/>* obj_ = <xsl:value-of select="@name"/>_val(v);
  g_assert(obj_ != NULL);
  gdome_<xsl:value-of select="$prefix"/>_unref(obj_, &amp;exc_);
  assert(exc_ == 0);
}

Gdome<xsl:value-of select="@name"/>*
<xsl:value-of select="@name"/>_val(value v)
{
  Gdome<xsl:value-of select="@name"/>* res_ = *((Gdome<xsl:value-of select="@name"/>**) Data_custom_val(v));
  g_assert(res_ != NULL);
  return res_;
}

value
Val_<xsl:value-of select="@name"/>(Gdome<xsl:value-of select="@name"/>* obj)
{
  static struct custom_operations ops = {
    "http://gmetadom.sourceforge.net/gdome_caml/events/<xsl:value-of select="@name"/>",
    ml_gdome_<xsl:value-of select="$prefix"/>_finalize,
    custom_compare_default,
    custom_hash_default,
    custom_serialize_default,
    custom_deserialize_default
  };
  
  value v = alloc_custom(&amp;ops, sizeof(Gdome<xsl:value-of select="@name"/>*), 0, 1);
  g_assert(obj != NULL);
  *((Gdome<xsl:value-of select="@name"/>**) Data_custom_val(v)) = obj;

  return v;
}

<xsl:apply-templates select="." mode="cast">
  <xsl:with-param name="name" select="@name"/>
  <xsl:with-param name="prefix" select="$prefix"/>
</xsl:apply-templates>

<xsl:apply-templates select="attribute">
  <xsl:with-param name="interface" select="@name"/>
  <xsl:with-param name="prefix" select="$prefix"/>
</xsl:apply-templates>

<xsl:apply-templates select="method">
  <xsl:with-param name="interface" select="@name"/>
  <xsl:with-param name="prefix" select="$prefix"/>
</xsl:apply-templates>

</xsl:template>

<xsl:template match="interface" mode="cast">
  <xsl:param name="name" select="''"/>
  <xsl:param name="prefix" select="''"/>
  
  <xsl:if test="@inherits">
   <xsl:variable name="parent" select="document(concat($uriprefix, concat('/', concat(@inherits, '.xml'))))/interface"/>
   <xsl:choose>
    <xsl:when test="$parent/@inherits">
     <xsl:apply-templates select="$parent" mode="cast">
      <xsl:with-param name="name" select="$name"/>
      <xsl:with-param name="prefix" select="$prefix"/>
     </xsl:apply-templates>
    </xsl:when>
    <xsl:otherwise>
<xsl:text>
value
ml_gdome_</xsl:text>
<xsl:value-of select="$prefix"/>_of_<xsl:call-template name="gdomePrefixOfType"><xsl:with-param name="type"><xsl:value-of select="@inherits"/></xsl:with-param></xsl:call-template>(value obj)
{
  CAMLparam1(obj);
  GdomeException exc_;
  Gdome<xsl:value-of select="$name"/>* obj_;
  <xsl:choose>
    <xsl:when test="$module = 'Core'">
  obj_ = gdome_cast_<xsl:value-of select="$prefix"/>((GdomeNode*) <xsl:value-of select="@inherits"/>_val(obj));
    </xsl:when>
    <xsl:when test="$module = 'Events'">
  obj_ = gdome_cast_<xsl:value-of select="$prefix"/>((GdomeEvent*) <xsl:value-of select="@inherits"/>_val(obj));
    </xsl:when>
    <xsl:otherwise>
#error
    </xsl:otherwise>
  </xsl:choose>
  if (obj_ == 0) throw_cast_exception("<xsl:value-of select="$name"/>");
  gdome_<xsl:value-of select="$prefix"/>_ref(obj_, &amp;exc_);
  if (exc_ != 0) throw_exception(exc_, "<xsl:value-of select="$name"/> casting from <xsl:value-of select="@inherits"/>");
  CAMLreturn(Val_<xsl:value-of select="$name"/>(obj_));
}

    </xsl:otherwise>
   </xsl:choose>
  </xsl:if>
</xsl:template>

<xsl:template match="attribute">
  <xsl:param name="interface" select="''"/>
  <xsl:param name="prefix" select="''"/>
  <xsl:param name="name" select="@name"/>
  <xsl:variable name="nullable" select="document($annotations)/Annotations/Attribute[@name = $name]/@nullable"/>
value
ml_gdome_<xsl:value-of select="$prefix"/>_get_<xsl:value-of select="@name"/>(value self)
{
  CAMLparam1(self);
  GdomeException exc_;
  <xsl:call-template name="gdomeTypeOfType">
    <xsl:with-param name="type" select="@type"/>
  </xsl:call-template> res_;
  <xsl:if test="@type = 'DOMString'">
  value res__;
  </xsl:if>
  res_ = gdome_<xsl:value-of select="$prefix"/>_<xsl:value-of select="@name"/>(<xsl:value-of select="$interface"/>_val(self), &amp;exc_);
  if (exc_ != 0) throw_exception(exc_, "<xsl:value-of select="$interface"/>.get_<xsl:value-of select="@name"/>");
  <xsl:call-template name="attrReturn">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="$nullable"/>
  </xsl:call-template>
}

<xsl:if test="not(@readonly)">value
ml_gdome_<xsl:value-of select="$prefix"/>_set_<xsl:value-of select="@name"/>(value self, value p_v)
{
  CAMLparam2(self, p_v);
  GdomeException exc_;
  <xsl:call-template name="convert-param">
    <xsl:with-param name="name" select="'v'"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="$nullable"/>
  </xsl:call-template>
  gdome_<xsl:value-of select="$prefix"/>_set_<xsl:value-of select="@name"/>(<xsl:value-of select="$interface"/>_val(self), <xsl:call-template name="pass-param">
    <xsl:with-param name="name" select="'v'"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="$nullable"/>
  </xsl:call-template>&amp;exc_);
  <xsl:call-template name="free-param">
    <xsl:with-param name="name" select="'v'"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="$nullable"/>
  </xsl:call-template>
  if (exc_ != 0) throw_exception(exc_, "<xsl:value-of select="$interface"/>.set_<xsl:value-of select="@name"/>");
  CAMLreturn(Val_unit);
}

</xsl:if>
</xsl:template>

<xsl:template match="method" >
  <xsl:param name="interface" select="''"/>
  <xsl:param name="prefix" select="''"/>
value
ml_gdome_<xsl:value-of select="$prefix"/>_<xsl:value-of select="@name"/>(value self<xsl:apply-templates select="parameters"/>)
{
  <xsl:apply-templates select="parameters" mode="declare"/>
  GdomeException exc_;
  <xsl:if test="returns/@type != 'void'">
    <xsl:call-template name="gdomeTypeOfType">
      <xsl:with-param name="type" select="returns/@type"/>
    </xsl:call-template> res_;
  </xsl:if>
  <xsl:apply-templates select="parameters" mode="convert">
    <xsl:with-param name="methodName" select="@name"/>
  </xsl:apply-templates>
  <xsl:if test="returns/@type = 'DOMString'">
  value res__;
  </xsl:if>
  <xsl:if test="returns/@type != 'void'">res_ = </xsl:if>gdome_<xsl:value-of select="$prefix"/>_<xsl:value-of select="@name"/>(<xsl:value-of select="$interface"/>_val(self), <xsl:apply-templates select="parameters" mode="pass">
    <xsl:with-param name="methodName" select="@name"/>
  </xsl:apply-templates>&amp;exc_);
  <xsl:apply-templates select="parameters" mode="free">
    <xsl:with-param name="methodName" select="@name"/>
  </xsl:apply-templates>
  if (exc_ != 0) throw_exception(exc_, "<xsl:value-of select="$interface"/>.<xsl:value-of select="@name"/>");
  <xsl:call-template name="methodReturn">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="type" select="returns/@type"/>
  </xsl:call-template>
}

<xsl:if test="count(parameters/param) &gt; 4">
value
ml_gdome_<xsl:value-of select="$prefix"/>_<xsl:value-of select="@name"/>_bytecode(value *argv, int argn)
{
  g_assert(argv != NULL);
  return ml_gdome_<xsl:value-of select="$prefix"/>_<xsl:value-of select="@name"/>(argv[0]<xsl:apply-templates select="parameters" mode="pass-bytecode"/>);
}

</xsl:if>
</xsl:template>

<xsl:template match="parameters">
  <xsl:apply-templates select="param"/>
</xsl:template>

<xsl:template match="parameters" mode="declare">
<xsl:choose>
  <xsl:when test="count(param) = 0">CAMLparam1(self);</xsl:when>
  <xsl:when test="count(param) = 1">CAMLparam2(self, p_<xsl:value-of select="param[1]/@name"/>);</xsl:when>
  <xsl:when test="count(param) = 2">CAMLparam3(self, p_<xsl:value-of select="param[1]/@name"/>, p_<xsl:value-of select="param[2]/@name"/>);</xsl:when>
  <xsl:when test="count(param) = 3">CAMLparam4(self, p_<xsl:value-of select="param[1]/@name"/>, p_<xsl:value-of select="param[2]/@name"/>, p_<xsl:value-of select="param[3]/@name"/>);</xsl:when>
  <xsl:otherwise>CAMLparam5(self, p_<xsl:value-of select="param[1]/@name"/>, p_<xsl:value-of select="param[2]/@name"/>, p_<xsl:value-of select="param[3]/@name"/>, p_<xsl:value-of select="param[4]/@name"/>);
  <xsl:choose>
      <xsl:when test="count(param) = 8">CAMLxparam4(p_<xsl:value-of select="param[5]/@name"/>, p_<xsl:value-of select="param[6]/@name"/>, p_<xsl:value-of select="param[7]/@name"/>, p_<xsl:value-of select="param[8]/@name"/>);
      </xsl:when>
      <xsl:otherwise>
#error "this number of parameters is not currently supported"
      </xsl:otherwise>
    </xsl:choose>
  </xsl:otherwise>
</xsl:choose>
<!-- to break the line and keep the indentation-->
<xsl:text>
  </xsl:text>
</xsl:template>

<xsl:template match="parameters" mode="convert">
  <xsl:param name="methodName" select="''"/>
  <xsl:apply-templates select="param[@type = 'DOMString']" mode="convert">
    <xsl:with-param name="methodName" select="$methodName"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="parameters" mode="pass">
  <xsl:param name="methodName" select="''"/>
  <xsl:apply-templates select="param" mode="pass">
    <xsl:with-param name="methodName" select="$methodName"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="parameters" mode="pass-bytecode">
  <xsl:apply-templates select="param" mode="pass-bytecode"/>
</xsl:template>

<xsl:template match="parameters" mode="free">
  <xsl:param name="methodName" select="''"/>
  <xsl:apply-templates select="param[@type = 'DOMString']" mode="free">
    <xsl:with-param name="methodName" select="$methodName"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="param">, value p_<xsl:value-of select="@name"/></xsl:template>

<xsl:template match="param" mode="convert">
  <xsl:param name="methodName" select="''"/>
  <xsl:param name="name" select="@name"/>
  <xsl:call-template name="convert-param">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="document($annotations)/Annotations/Method[@name = $methodName]/Param[@name = $name]/@nullable"/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="param" mode="pass">
  <xsl:param name="methodName" select="''"/>
  <xsl:variable name="name" select="@name"/>
  <xsl:call-template name="pass-param">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="document($annotations)/Annotations/Method[@name = $methodName]/Param[@name = $name]/@nullable"/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="param" mode="pass-bytecode">, argv[<xsl:value-of select="position()"/>]</xsl:template>

<xsl:template match="param" mode="free">
  <xsl:param name="methodName" select="''"/>
  <xsl:variable name="name" select="@name"/>
  <xsl:call-template name="free-param">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="type" select="@type"/>
    <xsl:with-param name="nullable" select="document($annotations)/Annotations/Method[@name = $methodName]/Param[@name = $name]/@nullable"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="convert-param">
  <xsl:param name="name" select="''"/>
  <xsl:param name="type" select="''"/>
  <xsl:param name="nullable" select="''"/>
  <xsl:if test="$type = 'DOMString'">
    <xsl:choose>
      <xsl:when test="$nullable = 'yes'">
  GdomeDOMString* p_<xsl:value-of select="$name"/>_ = ptr_val_option(p_<xsl:value-of select="$name"/>, DOMString_val);</xsl:when>
      <xsl:otherwise>
  GdomeDOMString* p_<xsl:value-of select="$name"/>_ = DOMString_val(p_<xsl:value-of select="$name"/>);</xsl:otherwise>
    </xsl:choose>
  </xsl:if>
</xsl:template>

<xsl:template name="pass-param">
  <xsl:param name="name" select="''"/>
  <xsl:param name="type" select="''"/>
  <xsl:param name="nullable" select="''"/>
  <xsl:choose>
    <xsl:when test="$type = 'boolean'">Bool_val(p_<xsl:value-of select="$name"/>), </xsl:when>
    <xsl:when test="$type = 'unsigned short'">Int_val(p_<xsl:value-of select="$name"/>), </xsl:when>
    <xsl:when test="$type = 'unsigned long'">Int_val(p_<xsl:value-of select="$name"/>), </xsl:when>
    <xsl:when test="$type = 'DOMTimeStamp'">Long_val(p_<xsl:value-of select="$name"/>), </xsl:when>
    <xsl:when test="$type = 'DOMString'">p_<xsl:value-of select="$name"/>_, </xsl:when>
    <xsl:otherwise>
      <xsl:choose>
        <xsl:when test="$nullable = 'yes'">ptr_val_option(p_<xsl:value-of select="$name"/>,<xsl:value-of select="$type"/>_val), </xsl:when>
	<xsl:otherwise><xsl:value-of select="$type"/>_val(p_<xsl:value-of select="$name"/>), </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="free-param">
  <xsl:param name="name" select="''"/>
  <xsl:param name="type" select="''"/>
  <xsl:param name="nullable" select="''"/>
  <xsl:if test="$type = 'DOMString'">
    <xsl:choose>
      <xsl:when test="$nullable = 'yes'">
  if (p_<xsl:value-of select="$name"/>_ != NULL) gdome_str_unref(p_<xsl:value-of select="$name"/>_);</xsl:when>
      <xsl:otherwise>
  g_assert(p_<xsl:value-of select="$name"/>_ != NULL);
  gdome_str_unref(p_<xsl:value-of select="$name"/>_);</xsl:otherwise>
    </xsl:choose>
  </xsl:if>
</xsl:template>

<xsl:template name="typeOfType">
  <xsl:param name="type" select="''"/>
  <xsl:choose>
    <xsl:when test="$type = 'boolean'">bool</xsl:when>
    <xsl:when test="$type = 'unsigned short'">unsigned short</xsl:when>
    <xsl:when test="$type = 'unsigned long'">unsigned long</xsl:when>
    <xsl:when test="$type = 'DOMTimeStamp'">unsigned long</xsl:when>
    <xsl:when test="$type = 'DOMTimeStamp'">DOMTimeStamp</xsl:when>
    <xsl:otherwise>Gdome<xsl:value-of select="$type"/>*</xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="gdomeNodeTypeOfType">
  <xsl:param name="type" select="''"/>
  <xsl:choose>
    <xsl:when test="$type = 'DocumentFragment'">DOCUMENT_FRAGMENT</xsl:when>
    <xsl:when test="$type = 'Document'">DOCUMENT</xsl:when>
    <xsl:when test="$type = 'Attr'">ATTRIBUTE</xsl:when>
    <xsl:when test="$type = 'Element'">ELEMENT</xsl:when>
    <xsl:when test="$type = 'Text'">TEXT</xsl:when>
    <xsl:when test="$type = 'Comment'">COMMENT</xsl:when>
    <xsl:when test="$type = 'CDATASection'">CDATA_SECTION</xsl:when>
    <xsl:when test="$type = 'DocumentType'">DOCUMENT_TYPE</xsl:when>
    <xsl:when test="$type = 'Notation'">NOTATION</xsl:when>
    <xsl:when test="$type = 'Entity'">ENTITY</xsl:when>
    <xsl:when test="$type = 'EntityReference'">ENTITY_REFERENCE</xsl:when>
    <xsl:when test="$type = 'ProcessingInstruction'">PROCESSING_INSTRUCTION</xsl:when>
    <xsl:otherwise>type</xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="attrReturn">
  <xsl:param name="name" select="''"/>
  <xsl:param name="type" select="''"/>
  <xsl:param name="nullable" select="''"/>
  <xsl:call-template name="return">
    <xsl:with-param name="type" select="$type"/>
    <xsl:with-param name="nullable" select="$nullable"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="methodReturn">
  <xsl:param name="name" select="''"/>
  <xsl:param name="type" select="''"/>
  <xsl:call-template name="return">
    <xsl:with-param name="type" select="$type"/>
    <xsl:with-param name="nullable" select="document($annotations)/Annotations/Method[@name = $name]/@nullable"/>
  </xsl:call-template>
</xsl:template>

<xsl:template name="return">
  <xsl:param name="type" select="''"/>
  <xsl:param name="nullable" select="''"/>
  <xsl:choose>
    <xsl:when test="$type = 'void'">CAMLreturn(Val_unit);</xsl:when>
    <xsl:when test="$type = 'boolean'">CAMLreturn(Val_bool(res_));</xsl:when>
    <xsl:when test="$type = 'unsigned short'">CAMLreturn(Val_int(res_));</xsl:when>
    <xsl:when test="$type = 'unsigned long'">CAMLreturn(Val_int(res_));</xsl:when>
    <xsl:when test="$type = 'DOMTimeStamp'">CAMLreturn(Val_long(res_));</xsl:when>
    <xsl:when test="$type = 'DOMString'">
      <xsl:choose>
        <xsl:when test="$nullable = 'yes'">res__ = Val_option_ptr(res_,Val_DOMString);
  if (res_ != NULL) gdome_str_unref(res_);
  CAMLreturn(res__);
</xsl:when>
        <xsl:otherwise>g_assert(res_ != NULL);
  res__ = Val_DOMString(res_);
  gdome_str_unref(res_);
  CAMLreturn(res__);
</xsl:otherwise>
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>
      <xsl:choose>
        <xsl:when test="$nullable = 'yes'">CAMLreturn(Val_option_ptr(res_,Val_<xsl:value-of select="$type"/>));</xsl:when>
        <xsl:otherwise>g_assert(res_ != NULL);
  CAMLreturn(Val_<xsl:value-of select="$type"/>(res_));</xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="exception">
  <xsl:value-of select="@name"/>
  <xsl:if test="position() &lt; last()">, </xsl:if>
</xsl:template>

</xsl:stylesheet>

