summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jesse.barnes@intel.com>2012-01-18 14:09:47 -0800
committerKristian Høgsberg <krh@bitplanet.net>2012-01-18 18:22:25 -0500
commit5cd047131185932e937b05f6a77b9833028acbab (patch)
treed4f1e603769a7ead60d4d07c0551398299305bae
parent4b5871e2b8be59b5dc3daa6fe00eb1bee80bfad6 (diff)
scanner: Support documentation elements
On Wed, 18 Jan 2012 12:29:37 -0800 "Kristensen, Kristian H" <kristian.h.kristensen@intel.com> wrote: > Yeah, that looks good. I was thinking of a separate <description> tag > to avoid stuffing too much into an attribute. How does this look? It adds a summary attribute to atomic elements, and a <description> tag with a summary for others. Spits out enum documentation like this: /** * wl_display_error - global error values * @WL_DISPLAY_ERROR_INVALID_OBJECT: server couldn't find object * @WL_DISPLAY_ERROR_INVALID_METHOD: method doesn't exist on the specified interface * @WL_DISPLAY_ERROR_NO_MEMORY: server is out of memory * * These errors are global and can be emitted in response to any server request. */ enum wl_display_error { WL_DISPLAY_ERROR_INVALID_OBJECT = 0, WL_DISPLAY_ERROR_INVALID_METHOD = 1, WL_DISPLAY_ERROR_NO_MEMORY = 2, }; and structure documentation like this: /** * wl_display - core global object * @bind: bind an object to the display * @sync: (none) * * The core global object. This is a special singleton object. It is used for * internal wayland protocol features. */ struct wl_display_interface { void (*bind)(struct wl_client *client, struct wl_resource *resource, uint32_t name, const char *interface, uint32_t version, uint32_t id); void (*sync)(struct wl_client *client, struct wl_resource *resource, uint32_t callback); };
-rw-r--r--protocol/wayland.xml19
-rw-r--r--src/scanner.c131
2 files changed, 146 insertions, 4 deletions
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index cdbbfd0..8d91187 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -30,7 +30,13 @@
<!-- The core global object. This is a special singleton object.
It is used for internal wayland protocol features. -->
<interface name="wl_display" version="1">
+ <description summary="core global object">
+ The core global object. This is a special singleton object.
+ It is used for internal wayland protocol features.
+ </description>
<request name="bind">
+ <description summary="bind an object to the display">
+ </description>
<arg name="name" type="uint"/>
<arg name="interface" type="string"/>
<arg name="version" type="uint"/>
@@ -54,9 +60,16 @@
</event>
<enum name="error">
- <entry name="invalid_object" value="0"/>
- <entry name="invalid_method" value="1"/>
- <entry name="no_memory" value="2"/>
+ <description summary="global error values">
+ These errors are global and can be emitted in response to any
+ server request.
+ </description>
+ <entry name="invalid_object" value="0"
+ summary="server couldn't find object"/>
+ <entry name="invalid_method" value="1"
+ summary="method doesn't exist on the specified interface"/>
+ <entry name="no_memory" value="2"
+ summary="server is out of memory"/>
</enum>
<!-- Notify the client of global objects. These are objects that
diff --git a/src/scanner.c b/src/scanner.c
index d0b555c..e3b4226 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -47,6 +47,11 @@ struct protocol {
char *copyright;
};
+struct description {
+ char *summary;
+ char *text;
+};
+
struct interface {
char *name;
char *uppercase_name;
@@ -55,6 +60,7 @@ struct interface {
struct wl_list event_list;
struct wl_list enumeration_list;
struct wl_list link;
+ struct description *description;
};
struct message {
@@ -66,6 +72,7 @@ struct message {
int type_index;
int all_null;
int destructor;
+ struct description *description;
};
enum arg_type {
@@ -90,12 +97,14 @@ struct enumeration {
char *uppercase_name;
struct wl_list entry_list;
struct wl_list link;
+ struct description *description;
};
struct entry {
char *name;
char *uppercase_name;
char *value;
+ char *summary;
struct wl_list link;
};
@@ -106,6 +115,7 @@ struct parse_context {
struct interface *interface;
struct message *message;
struct enumeration *enumeration;
+ struct description *description;
char character_data[8192];
int character_data_length;
};
@@ -124,6 +134,50 @@ uppercase_dup(const char *src)
return u;
}
+static char *
+desc_dup(char *src)
+{
+ char *u;
+ int i, j = 0, col = 0, line = 0, len;
+
+ len = strlen(src) * 2;
+ u = malloc(len); /* enough room for newlines & comments */
+ if (!u)
+ return NULL;
+
+ memset(u, 0, len);
+
+ /* Strip leading space */
+ for (i = 0; isspace(src[i]); i++)
+ ;
+
+ for (; src[i]; i++) {
+ /* Collapse multiple spaces into 1 */
+ if (isspace(src[i]) && isspace(src[i + 1]))
+ continue;
+
+ if (isspace(src[i]))
+ src[i] = ' ';
+
+ if (col > 72 && isspace(src[i])) {
+ if (src[i+1]) {
+ u[j++] = '\n';
+ u[j++] = ' ';
+ u[j++] = '*';
+ u[j++] = ' ';
+ }
+ line++;
+ col = 0;
+ } else {
+ u[j++] = src[i];
+ col++;
+ }
+ }
+ u[j++] = '\0';
+
+ return u;
+}
+
static void
fail(struct parse_context *ctx, const char *msg)
{
@@ -141,7 +195,8 @@ start_element(void *data, const char *element_name, const char **atts)
struct arg *arg;
struct enumeration *enumeration;
struct entry *entry;
- const char *name, *type, *interface_name, *value;
+ struct description *description;
+ const char *name, *type, *interface_name, *value, *summary;
int i, version;
name = NULL;
@@ -149,6 +204,8 @@ start_element(void *data, const char *element_name, const char **atts)
version = 0;
interface_name = NULL;
value = NULL;
+ summary = NULL;
+ description = NULL;
for (i = 0; atts[i]; i += 2) {
if (strcmp(atts[i], "name") == 0)
name = atts[i + 1];
@@ -160,6 +217,8 @@ start_element(void *data, const char *element_name, const char **atts)
value = atts[i + 1];
if (strcmp(atts[i], "interface") == 0)
interface_name = atts[i + 1];
+ if (strcmp(atts[i], "summary") == 0)
+ summary = atts[i + 1];
}
ctx->character_data_length = 0;
@@ -182,6 +241,7 @@ start_element(void *data, const char *element_name, const char **atts)
interface->name = strdup(name);
interface->uppercase_name = uppercase_dup(name);
interface->version = version;
+ interface->description = NULL;
wl_list_init(&interface->request_list);
wl_list_init(&interface->event_list);
wl_list_init(&interface->enumeration_list);
@@ -259,6 +319,7 @@ start_element(void *data, const char *element_name, const char **atts)
enumeration = malloc(sizeof *enumeration);
enumeration->name = strdup(name);
enumeration->uppercase_name = uppercase_dup(name);
+ enumeration->description = NULL;
wl_list_init(&enumeration->entry_list);
wl_list_insert(ctx->interface->enumeration_list.prev,
@@ -273,8 +334,32 @@ start_element(void *data, const char *element_name, const char **atts)
entry->name = strdup(name);
entry->uppercase_name = uppercase_dup(name);
entry->value = strdup(value);
+ if (summary)
+ entry->summary = strdup(summary);
+ else
+ entry->summary = NULL;
wl_list_insert(ctx->enumeration->entry_list.prev,
&entry->link);
+ } else if (strcmp(element_name, "description") == 0) {
+ if (summary == NULL)
+ fail(ctx, "description without summary");
+
+ description = malloc(sizeof *description);
+ if (summary)
+ description->summary = strdup(summary);
+ else
+ description->summary = NULL;
+
+ if (ctx->message)
+ ctx->message->description = description;
+ else if (ctx->enumeration)
+ ctx->enumeration->description = description;
+ else if (ctx->interface)
+ ctx->interface->description = description;
+ else
+ fprintf(stderr,
+ "<description> found in unsupported element\n");
+ ctx->description = description;
}
}
@@ -287,6 +372,17 @@ end_element(void *data, const XML_Char *name)
ctx->protocol->copyright =
strndup(ctx->character_data,
ctx->character_data_length);
+ } else if (strcmp(name, "description") == 0) {
+ char *text = strndup(ctx->character_data,
+ ctx->character_data_length);
+ if (text)
+ ctx->description->text = desc_dup(text);
+ ctx->description = NULL;
+ } else if (strcmp(name, "request") == 0 ||
+ strcmp(name, "event") == 0) {
+ ctx->message = NULL;
+ } else if (strcmp(name, "enum") == 0) {
+ ctx->enumeration = NULL;
}
}
@@ -489,10 +585,30 @@ emit_enumerations(struct interface *interface)
struct entry *entry;
wl_list_for_each(e, &interface->enumeration_list, link) {
+ struct description *desc = e->description;
+
printf("#ifndef %s_%s_ENUM\n",
interface->uppercase_name, e->uppercase_name);
printf("#define %s_%s_ENUM\n",
interface->uppercase_name, e->uppercase_name);
+
+ if (desc) {
+ printf("/**\n"
+ " * %s_%s - %s\n", interface->name,
+ e->name, desc->summary);
+ wl_list_for_each(entry, &e->entry_list, link) {
+ printf(" * @%s_%s_%s: %s\n",
+ interface->uppercase_name,
+ e->uppercase_name,
+ entry->uppercase_name,
+ entry->summary);
+ }
+ if (desc->text) {
+ printf(" *\n"
+ " * %s\n", desc->text);
+ }
+ printf(" */\n");
+ }
printf("enum %s_%s {\n", interface->name, e->name);
wl_list_for_each(entry, &e->entry_list, link)
printf("\t%s_%s_%s = %s,\n",
@@ -516,6 +632,19 @@ emit_structs(struct wl_list *message_list, struct interface *interface)
return;
is_interface = message_list == &interface->request_list;
+ if (interface->description) {
+ struct description *desc = interface->description;
+ printf("/**\n"
+ " * %s - %s\n", interface->name, desc->summary);
+ wl_list_for_each(m, message_list, link) {
+ struct description *mdesc = m->description;
+ printf(" * @%s: %s\n", m->name, mdesc ? mdesc->summary :
+ "(none)");
+ }
+ printf(" *\n"
+ " * %s\n"
+ " */\n", desc->text);
+ }
printf("struct %s_%s {\n", interface->name,
is_interface ? "interface" : "listener");