This switches the scanner to generate doxygen-compatible tags for the
generated protocol headers, and hooks up the doxygen build to generate server
and client-side API documentation.

Each protocol is a separate doxygen @page, with each interface a @subpage.
Wayland only has one protocol, wayland-protocols will have these nested.
Each protocol page has a list of interfaces and the copyright and description
where available.
All interfaces are grouped by doxygen @defgroup and @ingroups and appear in
"Modules" in the generated output. Each interface subpage has the description
and a link to the actual API doc.
Function, struct and #defines are documented in doxygen style and associated
with the matching interface.

Note that pages and groups have fixed HTML file names and are directly
linkable/bookmark-able.

The @mainpage is a separate file that's included at build time. It doesn't
contain much other than links to where the interesting bits are. It's a static
file though that supports markdown, so we can extend it easily in the future.

For doxygen we need the new options EXTRACT_ALL and OPTIMIZE_OUTPUT_FOR_C so
it scans C code properly. WARN_IF_DOC_ERROR is required to silence the
warnings when some parameters are documented but others aren't.

Signed-off-by: Peter Hutterer <[email protected]>
---
Generated output for wayland and wayland-protocols is here:
http://people.freedesktop.org/~whot/wayland-doxygen/

* as discussed in the other thread, this doesn't touch the current generated
  xml files, the current doc doesn't actually include the protocol API
  anyway.
* mainpage is separate because it's easier this way for wayland-protocols
* the generated code contains a lot of comment now but is still readable.
  Only duplication is the copyright (once at file level, once as protocol
  section), but that shouldn't hurt anyone.
* we should start including <description> tags at the <protocol> level. the
  scanner supports it and it provides extra info (see the tablet
  protocol in wayland-protocols)

 doc/doxygen/Makefile.am        |  27 +++++-
 doc/doxygen/mainpage.dox       |  13 +++
 doc/doxygen/wayland.doxygen.in |   4 +-
 src/scanner.c                  | 207 +++++++++++++++++++++++++++--------------
 4 files changed, 176 insertions(+), 75 deletions(-)
 create mode 100644 doc/doxygen/mainpage.dox

diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am
index a8bb95f..e80c401 100644
--- a/doc/doxygen/Makefile.am
+++ b/doc/doxygen/Makefile.am
@@ -1,7 +1,11 @@
 
 .SUFFIXES = .gv .png .map
 
-noinst_DATA = xml/Client/index.xml xml/Server/index.xml
+noinst_DATA = \
+              xml/Client/index.xml \
+              xml/Server/index.xml \
+              html/Client/index.html \
+              html/Server/index.html
 dist_noinst_DATA = wayland.doxygen.in
 
 scanned_src_files_shared =                             \
@@ -27,6 +31,17 @@ scanned_src_files_man =                                      
\
        $(top_srcdir)/src/wayland-client.h      \
        $(top_srcdir)/src/wayland-client-core.h
 
+extra_doxygen = \
+       mainpage.dox
+
+extra_doxygen_Server = \
+       $(top_builddir)/protocol/wayland-server-protocol.h \
+       $(extra_doxygen)
+
+extra_doxygen_Client = \
+       $(top_builddir)/protocol/wayland-client-protocol.h \
+       $(extra_doxygen)
+
 diagramsdir := $(srcdir)/dot
 diagramssrc := $(wildcard $(diagramsdir)/*.gv)
 diagrams := $(patsubst $(diagramsdir)/%,xml/%,$(diagramssrc:.gv=.png))
@@ -38,7 +53,7 @@ diagram_maps := $(patsubst 
$(diagramsdir)/%,xml/%,$(diagramssrc:.gv=.map))
 dist_man3_MANS = $(shell test -d man && find man/man3 -name "wl_*.3" -printf 
"man/man3/%P\n")
 
 # Listing various directories that might need to be created.
-alldirs := xml xml/Client xml/Server man/man3
+alldirs := xml xml/Client xml/Server man/man3 html/Client html/Server
 
 $(diagrams): $(diagramssrc)
 
@@ -51,6 +66,13 @@ xml/%/index.xml: $(top_srcdir)/src/scanner.c 
$(scanned_src_files_%) wayland.doxy
           echo "INPUT= $(scanned_src_files_$*)"; \
           ) | $(DOXYGEN) -
 
+html/%/index.html: $(scanned_src_files_%) wayland.doxygen $(diagrams) 
$(diagram_maps) | html/%
+       $(AM_V_GEN)(cat wayland.doxygen; \
+          echo "GENERATE_HTML=YES"; \
+          echo "HTML_OUTPUT=html/$*"; \
+          echo "INPUT= $(scanned_src_files_$*) $(extra_doxygen_$*)"; \
+          ) | $(DOXYGEN) -
+
 man/man3/wl_display.3: $(top_srcdir)/src/scanner.c $(scanned_src_files_man) 
wayland.doxygen | man/man3
        $(AM_V_GEN)(cat wayland.doxygen; \
           echo "GENERATE_MAN=YES"; \
@@ -74,6 +96,7 @@ all-local: man/man3/wl_display.3
 
 clean-local:
        rm -rf xml/
+       rm -rf html/
        rm -rf man/
 
 EXTRA_DIST = $(diagramssrc)
diff --git a/doc/doxygen/mainpage.dox b/doc/doxygen/mainpage.dox
new file mode 100644
index 0000000..8f9bf03
--- /dev/null
+++ b/doc/doxygen/mainpage.dox
@@ -0,0 +1,13 @@
+/**
+ * @mainpage
+ * Wayland protocol API documentation.
+ *
+ * @section ifaces Interfaces
+ * For the list of available interfaces, please see the
+ * <a href="modules.html">modules</a> list.
+ *
+ * @section protocols Protocols
+ * For the list of protocols, please see the
+ * <a href="pages.html">Related Pages</a>.
+ *
+ */
diff --git a/doc/doxygen/wayland.doxygen.in b/doc/doxygen/wayland.doxygen.in
index fb76b12..3ca2d00 100644
--- a/doc/doxygen/wayland.doxygen.in
+++ b/doc/doxygen/wayland.doxygen.in
@@ -13,4 +13,6 @@ MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
 DOT_MULTI_TARGETS      = YES
 ALIASES                += comment{1}="/* \1 *<!-- -->/"
-GENERATE_HTML          = NO
+OPTIMIZE_OUTPUT_FOR_C  = YES
+EXTRACT_ALL            = YES
+WARN_IF_DOC_ERROR      = NO
diff --git a/src/scanner.c b/src/scanner.c
index 7b0f482..c2b8378 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -762,9 +762,11 @@ emit_opcode_versions(struct wl_list *message_list, struct 
interface *interface)
 {
        struct message *m;
 
-       wl_list_for_each(m, message_list, link)
+       wl_list_for_each(m, message_list, link) {
+               printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
                printf("#define %s_%s_SINCE_VERSION\t%d\n",
                       interface->uppercase_name, m->uppercase_name, m->since);
+       }
 
        printf("\n");
 }
@@ -804,6 +806,7 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
        struct arg *a, *ret;
        int has_destructor, has_destroy;
 
+       printf("/** @ingroup iface_%s */\n", interface->name);
        printf("static inline void\n"
               "%s_set_user_data(struct %s *%s, void *user_data)\n"
               "{\n"
@@ -812,6 +815,7 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
               interface->name, interface->name, interface->name,
               interface->name);
 
+       printf("/** @ingroup iface_%s */\n", interface->name);
        printf("static inline void *\n"
               "%s_get_user_data(struct %s *%s)\n"
               "{\n"
@@ -837,7 +841,8 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
                exit(EXIT_FAILURE);
        }
 
-       if (!has_destroy && strcmp(interface->name, "wl_display") != 0)
+       if (!has_destroy && strcmp(interface->name, "wl_display") != 0) {
+               printf("/** @ingroup iface_%s */\n", interface->name);
                printf("static inline void\n"
                       "%s_destroy(struct %s *%s)\n"
                       "{\n"
@@ -846,6 +851,7 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
                       "}\n\n",
                       interface->name, interface->name, interface->name,
                       interface->name);
+       }
 
        if (wl_list_empty(message_list))
                return;
@@ -865,6 +871,7 @@ emit_stubs(struct wl_list *message_list, struct interface 
*interface)
                                ret = a;
                }
 
+               printf("/** @ingroup iface_%s */\n", interface->name);
                if (ret && ret->interface_name == NULL)
                        printf("static inline void *\n");
                else if (ret)
@@ -950,6 +957,16 @@ emit_event_wrappers(struct wl_list *message_list, struct 
interface *interface)
                return;
 
        wl_list_for_each(m, message_list, link) {
+               printf("/**\n"
+                      " * @ingroup iface_%s\n"
+                      " * Sends an %s event to the client owning the 
resource.\n",
+                      interface->name,
+                      m->name);
+               wl_list_for_each(a, &m->arg_list, link) {
+                       if (a->summary)
+                               printf(" * @param %s %s\n", a->name, 
a->summary);
+               }
+               printf(" */\n");
                printf("static inline void\n"
                       "%s_send_%s(struct wl_resource *resource_",
                       interface->name, m->name);
@@ -981,6 +998,31 @@ emit_event_wrappers(struct wl_list *message_list, struct 
interface *interface)
 }
 
 static void
+format_text_to_comment(const char *text, bool standalone_comment)
+{
+       int bol = 1, start = 0, i;
+
+       for (i = 0; text[i]; i++) {
+               if (bol && (text[i] == ' ' || text[i] == '\t')) {
+                       continue;
+               } else if (bol) {
+                       bol = 0;
+                       start = i;
+               }
+
+               if (text[i] == '\n' || text[i] == '\0') {
+                       printf("%s%s%.*s\n",
+                              i == 0 && standalone_comment ? "/*" : " *",
+                              (i - start) == 0 ? "" : " ",
+                              i - start, text + start);
+                       bol = 1;
+               }
+       }
+       if (standalone_comment)
+               printf(" */\n\n");
+}
+
+static void
 emit_enumerations(struct interface *interface)
 {
        struct enumeration *e;
@@ -996,28 +1038,23 @@ emit_enumerations(struct interface *interface)
 
                if (desc) {
                        printf("/**\n");
-                       desc_dump(desc->summary,
-                                 " * %s_%s - ",
-                                 interface->name, e->name);
-                       wl_list_for_each(entry, &e->entry_list, link) {
-                               desc_dump(entry->summary,
-                                         " * @%s_%s_%s: ",
-                                         interface->uppercase_name,
-                                         e->uppercase_name,
-                                         entry->uppercase_name);
-                       }
-                       if (desc->text) {
-                               printf(" *\n");
-                               desc_dump(desc->text, " * ");
-                       }
+                       printf(" * @ingroup iface_%s\n", interface->name);
+                       format_text_to_comment(desc->summary, false);
+                       if (desc->text)
+                               format_text_to_comment(desc->text, false);
                        printf(" */\n");
                }
                printf("enum %s_%s {\n", interface->name, e->name);
-               wl_list_for_each(entry, &e->entry_list, link)
+               wl_list_for_each(entry, &e->entry_list, link) {
+                       if (entry->summary)
+                               printf("\t/**\n"
+                                      "\t * %s\n"
+                                      "\t */\n", entry->summary);
                        printf("\t%s_%s_%s = %s,\n",
                               interface->uppercase_name,
                               e->uppercase_name,
                               entry->uppercase_name, entry->value);
+               }
                printf("};\n");
                printf("#endif /* %s_%s_ENUM */\n\n",
                       interface->uppercase_name, e->uppercase_name);
@@ -1034,20 +1071,11 @@ emit_structs(struct wl_list *message_list, struct 
interface *interface, enum sid
        if (wl_list_empty(message_list))
                return;
 
-       if (interface->description) {
-               struct description *desc = interface->description;
-               printf("/**\n");
-               desc_dump(desc->summary, " * %s - ", interface->name);
-               wl_list_for_each(m, message_list, link) {
-                       struct description *mdesc = m->description;
-                       desc_dump(mdesc ? mdesc->summary : "(none)",
-                                 " * @%s: ",
-                                 m->name);
-               }
-               printf(" *\n");
-               desc_dump(desc->text, " * ");
-               printf(" */\n");
-       }
+       printf("/**\n");
+       printf(" * @ingroup iface_%s\n", interface->name);
+       printf(" * @struct %s_%s\n", interface->name,
+              (side == SERVER) ? "interface" : "listener");
+       printf(" */\n");
        printf("struct %s_%s {\n", interface->name,
               (side == SERVER) ? "interface" : "listener");
 
@@ -1055,24 +1083,24 @@ emit_structs(struct wl_list *message_list, struct 
interface *interface, enum sid
                struct description *mdesc = m->description;
 
                printf("\t/**\n");
-               desc_dump(mdesc ? mdesc->summary : "(none)",
-                         "\t * %s - ", m->name);
-               wl_list_for_each(a, &m->arg_list, link) {
-                       if (side == SERVER && a->type == NEW_ID &&
-                           a->interface_name == NULL)
-                               printf("\t * @interface: name of the objects 
interface\n"
-                                      "\t * @version: version of the objects 
interface\n");
-
-
-                       desc_dump(a->summary ? a->summary : "(none)",
-                                 "\t * @%s: ", a->name);
-               }
                if (mdesc) {
+                       if (mdesc->summary)
+                               printf("\t * %s\n", mdesc->summary);
                        printf("\t *\n");
                        desc_dump(mdesc->text, "\t * ");
                }
+               wl_list_for_each(a, &m->arg_list, link) {
+                       if (side == SERVER && a->type == NEW_ID &&
+                           a->interface_name == NULL)
+                               printf("\t * @param interface name of the 
objects interface\n"
+                                      "\t * @param version version of the 
objects interface\n");
+
+                       if (a->summary)
+                               printf("\t * @param %s %s\n", a->name,
+                                      a->summary);
+               }
                if (m->since > 1) {
-                       printf("\t * @since: %d\n", m->since);
+                       printf("\t * @since %d\n", m->since);
                }
                printf("\t */\n");
                printf("\tvoid (*%s)(", m->name);
@@ -1112,6 +1140,9 @@ emit_structs(struct wl_list *message_list, struct 
interface *interface, enum sid
        printf("};\n\n");
 
        if (side == CLIENT) {
+           printf("/**\n"
+                  " * @ingroup %s_iface\n"
+                  " */\n", interface->name);
            printf("static inline int\n"
                   "%s_add_listener(struct %s *%s,\n"
                   "%sconst struct %s_listener *listener, void *data)\n"
@@ -1128,30 +1159,6 @@ emit_structs(struct wl_list *message_list, struct 
interface *interface, enum sid
 }
 
 static void
-format_copyright(const char *copyright)
-{
-       int bol = 1, start = 0, i;
-
-       for (i = 0; copyright[i]; i++) {
-               if (bol && (copyright[i] == ' ' || copyright[i] == '\t')) {
-                       continue;
-               } else if (bol) {
-                       bol = 0;
-                       start = i;
-               }
-
-               if (copyright[i] == '\n' || copyright[i] == '\0') {
-                       printf("%s%s%.*s\n",
-                              i == 0 ? "/*" : " *",
-                              (i - start) == 0 ? "" : " ",
-                              i - start, copyright + start);
-                       bol = 1;
-               }
-       }
-       printf(" */\n\n");
-}
-
-static void
 emit_types_forward_declarations(struct protocol *protocol,
                                struct wl_list *message_list,
                                struct wl_array *types)
@@ -1204,6 +1211,46 @@ get_include_name(bool core, enum side side)
 }
 
 static void
+emit_mainpage_blurb(const struct protocol *protocol, enum side side)
+{
+       struct interface *i;
+
+       printf("/**\n"
+              " * @page page_%s The %s protocol\n",
+              protocol->name, protocol->name);
+
+       if (protocol->description) {
+               if (protocol->description->summary) {
+                       printf(" * %s\n"
+                              " *\n", protocol->description->summary);
+               }
+
+               if (protocol->description->text) {
+                       printf(" * @section page_desc_%s Description\n", 
protocol->name);
+                       format_text_to_comment(protocol->description->text, 
false);
+                       printf(" *\n");
+               }
+       }
+
+       printf(" * @section page_ifaces_%s Interfaces\n", protocol->name);
+       wl_list_for_each(i, &protocol->interface_list, link) {
+               printf(" * - @subpage page_iface_%s - %s\n",
+                      i->name,
+                      i->description && i->description->summary ?  
i->description->summary : "");
+       }
+
+       if (protocol->copyright) {
+               printf(" * @section page_copyright_%s Copyright\n",
+                      protocol->name);
+               printf(" * <pre>\n");
+               format_text_to_comment(protocol->copyright, false);
+               printf(" * </pre>\n");
+       }
+
+       printf(" */\n");
+}
+
+static void
 emit_header(struct protocol *protocol, enum side side)
 {
        struct interface *i, *i_next;
@@ -1211,9 +1258,6 @@ emit_header(struct protocol *protocol, enum side side)
        const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
        char **p, *prev;
 
-       if (protocol->copyright)
-               format_copyright(protocol->copyright);
-
        printf("#ifndef %s_%s_PROTOCOL_H\n"
               "#define %s_%s_PROTOCOL_H\n"
               "\n"
@@ -1230,6 +1274,8 @@ emit_header(struct protocol *protocol, enum side side)
               protocol->uppercase_name, s,
               get_include_name(protocol->core_headers, side));
 
+       emit_mainpage_blurb(protocol, side);
+
        wl_array_init(&types);
        wl_list_for_each(i, &protocol->interface_list, link) {
                emit_types_forward_declarations(protocol, &i->request_list, 
&types);
@@ -1253,6 +1299,23 @@ emit_header(struct protocol *protocol, enum side side)
        printf("\n");
 
        wl_list_for_each(i, &protocol->interface_list, link) {
+               printf("/**\n"
+                      " * @page page_iface_%s %s\n",
+                      i->name, i->name);
+               if (i->description && i->description->text) {
+                       printf(" * @section page_iface_%s_desc Description\n",
+                              i->name);
+                       format_text_to_comment(i->description->text, false);
+               }
+               printf(" * @section page_iface_%s_api API\n"
+                      " * See @ref iface_%s.\n",
+                      i->name, i->name);
+               printf(" *\n"
+                      " * @defgroup iface_%s The %s interface\n",
+                      i->name, i->name);
+               if (i->description && i->description->text)
+                       format_text_to_comment(i->description->text, false);
+               printf(" */\n");
                printf("extern const struct wl_interface "
                       "%s_interface;\n", i->name);
        }
@@ -1396,7 +1459,7 @@ emit_code(struct protocol *protocol)
        char **p, *prev;
 
        if (protocol->copyright)
-               format_copyright(protocol->copyright);
+               format_text_to_comment(protocol->copyright, true);
 
        printf("#include <stdlib.h>\n"
               "#include <stdint.h>\n"
-- 
2.4.3

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to