Blame tools/enums-to-docbook.pl

Packit Service b23acc
#!/usr/bin/perl -n
Packit Service b23acc
# SPDX-License-Identifier: GPL-2.0+
Packit Service b23acc
#
Packit Service b23acc
# Copyright (C) 2016 Red Hat, Inc.
Packit Service b23acc
#
Packit Service b23acc
Packit Service b23acc
# This tool formats enums along with their Gtk-Doc comments from a header
Packit Service b23acc
# file and produces a Docbook refentry suitable for inclusion in the D-Bus
Packit Service b23acc
# API rederence documentation.
Packit Service b23acc
#
Packit Service b23acc
# The output differs from Gtk-Doc: only enums are considered and are
Packit Service b23acc
# printed along with the values that are need to stay stable.
Packit Service b23acc
Packit Service b23acc
use strict;
Packit Service b23acc
use warnings;
Packit Service b23acc
Packit Service b23acc
our $name;
Packit Service b23acc
our $desc;
Packit Service b23acc
our $choice;
Packit Service b23acc
our @choices;
Packit Service b23acc
our $val;
Packit Service b23acc
Packit Service b23acc
BEGIN {
Packit Service b23acc
my $id = shift @ARGV or die "Missing ID";
Packit Service b23acc
my $nm = shift @ARGV or die "Missing title";
Packit Service b23acc
print <
Packit Service b23acc
Packit Service b23acc
Packit Service b23acc
Packit Service b23acc
Packit Service b23acc
<refentry id="$id">
Packit Service b23acc
  <refmeta>
Packit Service b23acc
    <refentrytitle role="top_of_page" id="$id.top_of_page">$nm</refentrytitle>
Packit Service b23acc
    <manvolnum>3</manvolnum>
Packit Service b23acc
    <refmiscinfo>$nm</refmiscinfo>
Packit Service b23acc
  </refmeta>
Packit Service b23acc
  <refnamediv>
Packit Service b23acc
    <refname>$nm</refname>
Packit Service b23acc
    <refpurpose></refpurpose>
Packit Service b23acc
  </refnamediv>
Packit Service b23acc
Packit Service b23acc
END
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
# Increment a value keeping the format (e.g. 0x000666 is incremented to 0x000667,
Packit Service b23acc
# while 9 becomes 10.
Packit Service b23acc
sub inc
Packit Service b23acc
{
Packit Service b23acc
	my $val = shift;
Packit Service b23acc
Packit Service b23acc
	if ($val =~ /^-?\d+$/) {
Packit Service b23acc
		my $len = length $val;
Packit Service b23acc
		if ($val =~ /^-/ && ($val + 1 == 0)) {
Packit Service b23acc
			$len = $len - 1
Packit Service b23acc
		}
Packit Service b23acc
		return sprintf "%0${len}d", $val + 1;
Packit Service b23acc
	} elsif ($val =~ /^0x(.+)$/) {
Packit Service b23acc
		my $len = length $1;
Packit Service b23acc
		return sprintf "0x%0${len}x", hex ($1) + 1;
Packit Service b23acc
	}
Packit Service b23acc
	die "'$val' used in previous enum value can not be incremented";
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
# The Gtk-Doc to docbook translation happens here. We don't support
Packit Service b23acc
# everything Gtk-Doc does.
Packit Service b23acc
sub fmt
Packit Service b23acc
{
Packit Service b23acc
	$_ = shift;
Packit Service b23acc
	s/\#([^\s\.]+)/<link linkend="$1">$1<\/link>/gm;
Packit Service b23acc
	s/\s*(.*)/<para>$1<\/para>/gm;
Packit Service b23acc
	$_;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
chomp;
Packit Service b23acc
Packit Service b23acc
if (/^\/\*\*$/) {
Packit Service b23acc
	# Start of a documentation comment
Packit Service b23acc
	$name = '';
Packit Service b23acc
	$desc = '';
Packit Service b23acc
	$choice = undef;
Packit Service b23acc
	@choices = ();
Packit Service b23acc
} elsif (/^ \* (.+):$/) {
Packit Service b23acc
	# The name
Packit Service b23acc
	die "Duplicate name '$1': already processing '$name'" if $name;
Packit Service b23acc
	$name = $1;
Packit Service b23acc
} elsif (/^ \* @(\S+):\s+(.*)$/) {
Packit Service b23acc
	# The enum choice documentation
Packit Service b23acc
	$choice = $1;
Packit Service b23acc
	die "Documentation for '$1' already seen" if grep { $_->[0] eq $choice } @choices;
Packit Service b23acc
	push @choices, [ $choice, $2 ]
Packit Service b23acc
} elsif (/^ \*\s+(.*)$/) {
Packit Service b23acc
	# Text. Either a choice documentation, a description or continuation of either
Packit Service b23acc
	if (defined $choice) {
Packit Service b23acc
		my ($this) = grep { $_->[0] eq $choice } @choices;
Packit Service b23acc
		$this->[1] .= " $1";
Packit Service b23acc
	} elsif (defined $desc) {
Packit Service b23acc
		$desc .= " " if $desc;
Packit Service b23acc
		$desc .= $1;
Packit Service b23acc
	}
Packit Service b23acc
} elsif (/^ \*$/) {
Packit Service b23acc
	# A separator line. Either starts the description or breaks a paragraph.
Packit Service b23acc
	$desc .= "\n" if $desc;
Packit Service b23acc
	$choice = undef;
Packit Service b23acc
} elsif (/^ \*+\/$/) {
Packit Service b23acc
	# End of the doc comment
Packit Service b23acc
	$choice = undef;
Packit Service b23acc
} elsif (/^typedef enum/) {
Packit Service b23acc
	# Start of an enum
Packit Service b23acc
	$val = -1;
Packit Service b23acc
} elsif (/^\s+(\S+)\s+=\s+([^,\s]+)/) {
Packit Service b23acc
	# A choice with a literal value
Packit Service b23acc
	next unless @choices;
Packit Service b23acc
	die "Saw enum value '$1', but didn't see start of enum before" unless defined $val;
Packit Service b23acc
	$val = $2;
Packit Service b23acc
	my ($this) = grep { $_->[0] eq $1 } @choices;
Packit Service b23acc
	die "Documentation for value '$1' missing" unless $this;
Packit Service b23acc
	$this->[2] = "= <literal>$val</literal>";
Packit Service b23acc
} elsif (/^\s+([^,\s]+),?$/) {
Packit Service b23acc
	# A choice without a literal value
Packit Service b23acc
	next unless @choices;
Packit Service b23acc
	die "Saw enum value '$1', but didn't see start of enum before" unless defined $val;
Packit Service b23acc
	my ($this) = grep { $_->[0] eq $1 } @choices;
Packit Service b23acc
	die "Documentation for value '$1' missing" unless $this;
Packit Service b23acc
	$val = inc $val;
Packit Service b23acc
	$this->[2] = "= <literal>$val</literal>";
Packit Service b23acc
} elsif (/^\} ([^;]+);/) {
Packit Service b23acc
	# End of an enum
Packit Service b23acc
	next unless defined $name;
Packit Service b23acc
	die "Name of the enum '$1' different than documented '$name'" if $1 ne $name;
Packit Service b23acc
Packit Service b23acc
	@choices = grep { $_->[0] !~ /_LAST$/ } @choices;
Packit Service b23acc
	foreach (@choices) {
Packit Service b23acc
		die "'$_->[0]' documented, but not present in enum" unless defined $_->[2]
Packit Service b23acc
	}
Packit Service b23acc
Packit Service b23acc
	$desc = fmt $desc;
Packit Service b23acc
	print <
Packit Service b23acc
  <refsect2 id="$name" role="enum">
Packit Service b23acc
    <title>enum $name</title>
Packit Service b23acc
    <indexterm zone="$name">
Packit Service b23acc
      <primary>$name</primary>
Packit Service b23acc
    </indexterm>
Packit Service b23acc
    <para>$desc</para>
Packit Service b23acc
    <refsect3 role="enum_members">
Packit Service b23acc
      <title>Values</title>
Packit Service b23acc
      <informaltable role="enum_members_table" pgwide="1" frame="none">
Packit Service b23acc
        <tgroup cols="4">
Packit Service b23acc
          <colspec colname="enum_members_name" colwidth="300px" />
Packit Service b23acc
          <colspec colname="enum_members_value" colwidth="100px"/>
Packit Service b23acc
          <colspec colname="enum_members_description" />
Packit Service b23acc
          
Packit Service b23acc
END
Packit Service b23acc
	foreach (@choices) {
Packit Service b23acc
		my ($name, $desc, $val) = map { fmt $_ } @$_;
Packit Service b23acc
		print <
Packit Service b23acc
            <row role="constant">
Packit Service b23acc
              <entry role="enum_member_name">$name</entry>
Packit Service b23acc
              <entry role="enum_member_value">$val</entry>
Packit Service b23acc
              <entry role="enum_member_description">$desc</entry>
Packit Service b23acc
            </row>
Packit Service b23acc
END
Packit Service b23acc
	print <
Packit Service b23acc
          
Packit Service b23acc
        </tgroup>
Packit Service b23acc
      </informaltable>
Packit Service b23acc
    </refsect3>
Packit Service b23acc
  </refsect2>
Packit Service b23acc
Packit Service b23acc
END
Packit Service b23acc
Packit Service b23acc
	$name = undef;
Packit Service b23acc
	$desc = undef;
Packit Service b23acc
	$choice = undef;
Packit Service b23acc
	$val = undef;
Packit Service b23acc
	@choices = ();
Packit Service b23acc
} else {
Packit Service b23acc
	# Only care about other lines if we're parsing an enum
Packit Service b23acc
	next unless $val;
Packit Service b23acc
	s/\/\*.*\*\///g;
Packit Service b23acc
	die "Unexpected input '$_' while parsing enum" unless /^\s*$/;
Packit Service b23acc
}
Packit Service b23acc
Packit Service b23acc
END {
Packit Service b23acc
print <
Packit Service b23acc
</refentry>
Packit Service b23acc
END
Packit Service b23acc
}