#! /usr/bin/perl

while (<>) {
    if (my ($class, $super) = /boilerplate for ([a-zA-Z0-9_]+), a subclass of ([a-zA-Z0-9_]+)/) {
	while (<>) {
	    last if //;
	}
	print <<EOF;
/* This boilerplate for ${class}, a subclass of ${super}, was
   autogenerated by mk-class-boilerplate. */

#include <assert.h>
#include "libpspp/cast.h"

extern const struct ${super}_class ${class}_class;

/* Returns true if SUPER is a ${class}, otherwise false. */
static inline bool
is_${class} (const struct ${super} *super)
{
  return super->class == &${class}_class;
}

/* Returns SUPER converted to ${class}.  SUPER must be a ${class}, as
   reported by is_${class}. */
static inline struct ${class} *
to_${class} (const struct ${super} *super)
{
  assert (is_${class} (super));
  return UP_CAST (super, struct ${class}, ${super});
}

/* Returns INSTANCE converted to ${super}. */
static inline struct ${super} *
${class}_super (const struct ${class} *instance)
{
  return CONST_CAST (struct ${super} *, &instance->${super});
}

/* Increments INSTANCE's reference count and returns INSTANCE. */
static inline struct ${class} *
${class}_ref (const struct ${class} *instance)
{
  return to_${class} (${super}_ref (&instance->${super}));
}

/* Decrements INSTANCE's reference count, then destroys INSTANCE if
   the reference count is now zero. */
static inline void
${class}_unref (struct ${class} *instance)
{
  ${super}_unref (&instance->${super});
}

/* Returns true if INSTANCE's reference count is greater than 1,
   false otherwise. */
static inline bool
${class}_is_shared (const struct ${class} *instance)
{
  return ${super}_is_shared (&instance->${super});
}

EOF
	if ($super ne 'output_item') {
	    print <<EOF;
static inline void
${class}_submit (struct ${class} *instance)
{
  ${super}_submit (&instance->${super});
}
EOF
	} else {
	    print "void ${class}_submit (struct ${class} *);\n";
	}
    }
    print;
}
