Havoc Pennington (hp@redhat.com)
19 Jan 2000 17:24:36 -0500

The current defs files are missing lots of information that we might
like to have, and aren't extensible. I've taken the gtk-doc code and
changed it to be a more modular gtk-header-file-scanner; it can
autogenerate (more or less) the current defs file format. However I
think we need a new format; here is a proposal, based on a proposal
Elliot made several months ago.

Comments encouraged.

Elliot's proposal: http://www.gnome.org/mailing-lists/archives/gtk-devel-list/1999-September/0027.shtml

Proposed format:

 - the proposed format is totally cumbersome, just remember you don't
   have to type it in :-) it's machine-generated and made for
   machine-reading

 - should have small s-expressions, not deeply nested, because this is
   easier to parse. the price is duplicate information. For example
   Elliot's proposal has this:

    (module Gtk
       (object Blah
          (method Foo)))

   note that the (module Gtk) expression will be several thousand lines.

  At least for the current gnome-python setup it's much easier to deal
  with:

  (module Gtk) ;; Gtk module exists

  (object Blah
   (in-module Gtk))

  (method Foo
   (of-object Blah Gtk))

  Basically the stack is smaller and you have to do less
  tree-walking.

  The redundant information isn't a concern, we are generating all
  this with a perl script anyway. Also I think it's easier
  to autogenerate stuff if it's less "entangled"

  Of course some nesting is needed or things get ridiculous (e.g. the
  arguments to functions, etc.)

 - The overall syntax might be:

     (type-of-thing-being-defined name-used-to-refer-to-this-thing
       (attribute-name attribute-value-depending-on-the-attribute)
       (attribute-name attribute-value-depending-on-the-attribute)
       (attribute-name attribute-value-depending-on-the-attribute))

Some initial types to define and their attributes:

===
(module module-name
  (submodule-of module-name)) ;; submodule is optional

Ex: (module Gtk)
Ex: (module Rgb
      (submodule-of Gdk))

modules are later referred to with a list of module names, like
(Gdk Rgb) or (Gtk)

===

(type
 (alias some-unique-identifier)
 (in-module module-name) ;; optional, gchar* is not in a module
 (c-name name-of-symbol-in-C)
 (really-const boolean-is-const)) ;; attribute used for gchar* return
                                  ;; values primarily, indicates broken constness

Ex: (type
     (alias broken_const_string)
     (c-name gchar*)
     (really-const #t))

    (type
     (alias GtkWidget**)
     (c-name GtkWidget**))

"Type" bindings are automatically assumed for objects, boxed types,
etc. as defined below.

The alias field is used to refer to the type later on.

If the C type has spaces they are converted to hyphens:
 (type
    (alias const-gchar*
     (c-name const-gchar*)))

So hyphens have to go back to spaces for binding generators that
output C code.

===
(object object-name
   (in-module module-name-list)
   (parent object-name optional-module-name-if-different)
   (abstract boolean-is-abstract-class) ;; omit for default of #f
   (c-name name-of-the-object-in-C)
   (field type-alias-of-struct-field name-of-struct-field))


Ex: (object Widget
      (in-module (Gtk))
      (parent Object) ;; could say (parent Object (Gtk))
      (abstract #t)
      (c-name GtkWidget)
      (field GdkWindow* window))

An "object" declaration automatically implies the type declaration:

(type
  (alias pointer-to-c-name)
  (c-name pointer-to-c-name))

Ex: (type (alias GtkWidget*) (c-name GtkWidget*))

Of course many language binding generators can just ignore this
implicit declaration.

===

(function function-name
  (in-module module-name-list)
  (c-name function-name)
  (return-type return-value-type) ;; defaults to void
  (argument argument-type-alias argument-name) ;; as many of these as you want
)

Ex:
  (function init
    (in-module (Gdk Rgb)
    (c-name gdk_rgb_init)))

Ex:
  (function cmap_new
    (in-module (Gdk Rgb))
    (c-name gdk_rgb_cmap_new)
    (return-type GdkRgbCmap*)
    (argument guint32* colors)
    (argument gint n_colors))

===
(method method-name
  (is-constructor boolean-is-a-constructor) ;; omit for default of #f
  (of-object object-name module-name)
  ;; retval/arg attributes as for (function), but with first argument omitted
  )

Ex:
  (method set_text
     (of-object Label (Gtk))
     (argument const-gchar* str))

===
(argument arg-name
   (of-object object-we-are-an-argument-of optional-objects-module)
   (type argument-type) ;; not sure what to put for type
   ;; flags all default to #f
   (readable bool-value)
   (writeable bool-value)
   (run-action bool-value)
   (construct-only bool-value))

Ex:
  (argument label
     (of-object Label (Gtk))
     (type gchar*) ;; ????
     (readable #t)
     (writeable #t))

===
(signal signal-name
  (of-object object-we-are-a-signal-of optional-objects-module)
  ;; return value and arguments as for a function, omitting the object
  ;; and user data arguments

  ;; what other properties matter for a signal?
)

Ex:
  (signal select_row
     (of-object CList (Gtk))
     ;; return type defaults to void
     (argument gint row)
     (argument gint column)
     (argument GdkEvent* event))

===
(enum enum-name
  (of-object objname module) ;; in-module and of-object are mutually exclusive
  (in-module modname)
  (c-name name-in-c)
  (value value-name-noprefixes-hyphen-lowercase value-c-name))

Ex:

  (enum DirectionType
    (in-module Gtk)
    (c-name GtkDirectionType)
    (tab-forward GTK_DIR_TAB_FORWARD)
    (tab-backward GTK_DIR_TAB_BACKWARD)
    (up GTK_DIR_UP)
    (down GTK_DIR_DOWN)
    (left GTK_DIR_LEFT)
    (right GTK_DIR_RIGHT))

  (enum Pos
    (of-object CTree (Gtk))
    (c-name GtkCTreePos)
    (before GTK_CTREE_POS_BEFORE)
    (as-child GTK_CTREE_POS_AS_CHILD)
    (after GTK_CTREE_POS_AFTER))

===
(flags) is just like enum, but some bindings may wrap enums and flags differently.

===
(boxed boxed-name
  (in-module modname)
  (c-name c-name)
  (ref-func func-to-increase-refcount)
  (unref-func func-to-decrease-refcount)
  (copy-func func-to-copy)
  (destroy-func func-to-destroy))

Ex:

 (boxed Pixmap
   (in-module (Gdk))
   (c-name GdkPixmap)
   (ref-func pixmap_ref)
   (unref-func pixmap_unref))

This implies the type alias GdkPixmap* to the C type GdkPixmap*

===

(user-function name
  (in-module module)
  (c-name c-typedef-name)
  ;; return-type and arguments as for (function)
)

Ex:

 (user-function PrintFunc
    (in-module (Gtk))
    (argument gpointer func_data)
    (argument gchar* str))

===

(typedef new-name
  (in-module module)
  (c-name c-full-name)
  (orig-type alias-of-orig-type))

Ex:

 (typedef Type
   (in-module (Gtk))
   (c-name GtkType)
   (orig-type guint))
