Skip to content

Commit

Permalink
Add support for C++ namespaces (Issue #7)
Browse files Browse the repository at this point in the history
- codedoc.c: Prefix all type/function/variable names with namespace, if used.
- codedoc.xsd: Drop old namespaceType since it was never used and doesn't fit
  well with how the documentation is generated anyways.
- testfiles/namespace.cxx: Add implementations of class/struct functions.
- *: bump version and changelog.
  • Loading branch information
michaelrsweet committed Dec 28, 2019
1 parent 9f8625e commit 5fd7dfc
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 67 deletions.
2 changes: 1 addition & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: How to Use the codedoc Utility
author: Michael R Sweet
copyright: Copyright © 2003-2019 by Michael R Sweet
version: 3.3
version: 3.4
...

Introduction
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# information.
#

VERSION = 3.3
VERSION = 3.4
prefix = $(DESTDIR)/usr/local
includedir = $(prefix)/include
bindir = $(prefix)/bin
Expand Down Expand Up @@ -56,6 +56,7 @@ TESTOPTIONS = \
--footer README.md

test: codedoc
rm -f test.xml
./codedoc $(TESTOPTIONS) test.xml testfiles/*.cxx >test.html
./codedoc $(TESTOPTIONS) --man test test.xml >test.man
./codedoc $(TESTOPTIONS) --epub test.epub test.xml
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Codedoc v3.3
Codedoc v3.4
============

Codedoc is a general-purpose utility which scans HTML, markdown, C, and C++
Expand All @@ -13,9 +13,10 @@ Codedoc was originally bundled with the Mini-XML library as the `mxmldoc`
utility.


Changes in vCURRENT
-------------------
Changes in v3.4
---------------

- Added support for C++ namespaces (Issue #7)
- Silenced some warnings from the LGTM security scanner.


Expand Down
105 changes: 87 additions & 18 deletions codedoc.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ static void markdown_write_block(FILE *out, mmd_t *parent, int mode);
static void markdown_write_leaf(FILE *out, mmd_t *node, int mode);
static mxml_node_t *new_documentation(mxml_node_t **codedoc);
static void safe_strcpy(char *dst, const char *src);
static int scan_file(filebuf_t *file, mxml_node_t *doc);
static int scan_file(filebuf_t *file, mxml_node_t *doc, const char *nsname);
static void sort_node(mxml_node_t *tree, mxml_node_t *func);
static int stringbuf_append(stringbuf_t *buffer, int ch);
static void stringbuf_clear(stringbuf_t *buffer);
Expand Down Expand Up @@ -507,7 +507,7 @@ main(int argc, /* I - Number of command-line args */
mxmlDelete(doc);
return (1);
}
else if (!scan_file(&file, codedoc))
else if (!scan_file(&file, codedoc, NULL))
{
fclose(file.fp);
mxmlDelete(doc);
Expand Down Expand Up @@ -2361,11 +2361,13 @@ safe_strcpy(char *dst, /* I - Destination string */

static int /* O - 1 on success, 0 on error */
scan_file(filebuf_t *file, /* I - File to scan */
mxml_node_t *tree) /* I - Function tree */
mxml_node_t *tree, /* I - Function tree */
const char *nsname) /* I - Namespace name */
{
int state, /* Current parser state */
braces, /* Number of braces active */
parens; /* Number of active parenthesis */
parens, /* Number of active parenthesis */
tree_is_scu; /* Is the tree a struct, class, or union? */
int ch; /* Current character */
stringbuf_t buffer; /* String buffer */
const char *scope; /* Current variable/function scope */
Expand All @@ -2386,6 +2388,8 @@ scan_file(filebuf_t *file, /* I - File to scan */
int whitespace; /* Current whitespace value */
const char *string, /* Current string value */
*next_string; /* Next string value */
int nskeyword = 0; /* Namespace keyword seen? */
char nsnamestr[1024] = ""; /* Namespace name string */
#if DEBUG > 1
mxml_node_t *temp; /* Temporary node */
int oldstate, /* Previous state */
Expand All @@ -2403,7 +2407,7 @@ scan_file(filebuf_t *file, /* I - File to scan */
#endif /* DEBUG > 1 */


DEBUG_printf("scan_file(file.filename=\"%s\", .fp=%p, tree=%p)\n", file->filename, file->fp, tree);
DEBUG_printf("scan_file(file.filename=\"%s\", .fp=%p, tree=%p, nsname=\"%s\")\n", file->filename, file->fp, tree, nsname);

/*
* Initialize the finite state machine...
Expand All @@ -2423,6 +2427,7 @@ scan_file(filebuf_t *file, /* I - File to scan */
typedefnode = NULL;
structclass = NULL;
fstructclass = NULL;
tree_is_scu = !strcmp(mxmlGetElement(tree), "class") || !strcmp(mxmlGetElement(tree), "struct") || !strcmp(mxmlGetElement(tree), "union");

if (!strcmp(mxmlGetElement(tree), "class"))
scope = "private";
Expand Down Expand Up @@ -2493,6 +2498,19 @@ scan_file(filebuf_t *file, /* I - File to scan */
break;

case '{' :
if (nskeyword)
{
if (!scan_file(file, tree, nsnamestr))
{
mxmlDelete(comment);
return (0);
}

nskeyword = 0;
nsnamestr[0] = '\0';
break;
}

string = get_nth_text(type, 0, &whitespace);
next_string = get_nth_text(type, 1, NULL);

Expand Down Expand Up @@ -2563,7 +2581,13 @@ scan_file(filebuf_t *file, /* I - File to scan */

if (next_string)
{
mxmlElementSetAttr(structclass, "name", next_string);
if (nsname)
{
mxmlElementSetAttrf(structclass, "name", "%s::%s", nsname, next_string);
mxmlSetText(get_nth_child(type, 1), 1, mxmlElementGetAttr(structclass, "name"));
}
else
mxmlElementSetAttr(structclass, "name", next_string);
sort_node(tree, structclass);
}

Expand Down Expand Up @@ -2624,7 +2648,7 @@ scan_file(filebuf_t *file, /* I - File to scan */
update_comment(structclass, mxmlGetLastChild(comment));
mxmlAdd(description, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, mxmlGetLastChild(comment));

if (!scan_file(file, structclass))
if (!scan_file(file, structclass, nsname))
{
mxmlDelete(comment);
return (0);
Expand Down Expand Up @@ -2659,7 +2683,14 @@ scan_file(filebuf_t *file, /* I - File to scan */

if (next_string)
{
mxmlElementSetAttr(enumeration, "name", next_string);
if (nsname)
{
mxmlElementSetAttrf(enumeration, "name", "%s::%s", nsname, next_string);
mxmlSetText(get_nth_child(type, 1), 1, mxmlElementGetAttr(enumeration, "name"));
}
else
mxmlElementSetAttr(enumeration, "name", next_string);

sort_node(tree, enumeration);
}

Expand Down Expand Up @@ -2697,7 +2728,7 @@ scan_file(filebuf_t *file, /* I - File to scan */
}
else if (type && string && !strcmp(string, "extern"))
{
if (!scan_file(file, tree))
if (!scan_file(file, tree, nsname))
{
mxmlDelete(comment);
return (0);
Expand Down Expand Up @@ -3429,6 +3460,17 @@ scan_file(filebuf_t *file, /* I - File to scan */

if (!braces)
{
if (!strcmp(str, "namespace"))
{
nskeyword = 1;
break;
}
else if (nskeyword)
{
strlcpy(nsnamestr, str, sizeof(nsnamestr));
break;
}

if (!type || !mxmlGetFirstChild(type))
{
if (!strcmp(mxmlGetElement(tree), "class"))
Expand Down Expand Up @@ -3478,21 +3520,33 @@ scan_file(filebuf_t *file, /* I - File to scan */
function = mxmlNewElement(MXML_NO_PARENT, "function");
if ((ptr = strchr(str, ':')) != NULL && ptr[1] == ':')
{
char name[1024]; /* Struct/class name */

*ptr = '\0';
ptr += 2;

if ((fstructclass = mxmlFindElement(tree, tree, "class", "name", str, MXML_DESCEND_FIRST)) == NULL)
fstructclass = mxmlFindElement(tree, tree, "struct", "name", str, MXML_DESCEND_FIRST);
if (nsname)
snprintf(name, sizeof(name), "%s::%s", nsname, str);
else
strlcpy(name, str, sizeof(name));

DEBUG_printf("looking for struct or class '%s' under %p(%s)...\n", name, tree, mxmlGetElement(tree));
if ((fstructclass = mxmlFindElement(tree, tree, "class", "name", name, MXML_DESCEND_FIRST)) == NULL)
fstructclass = mxmlFindElement(tree, tree, "struct", "name", name, MXML_DESCEND_FIRST);
DEBUG_printf("fstructclass=%p\n", fstructclass);
}
else
ptr = str;

mxmlElementSetAttr(function, "name", ptr);
if (nsname && !fstructclass && !tree_is_scu)
mxmlElementSetAttrf(function, "name", "%s::%s", nsname, ptr);
else
mxmlElementSetAttr(function, "name", ptr);

if (scope)
mxmlElementSetAttr(function, "scope", scope);

DEBUG_printf("function: %s\n", str);
DEBUG_printf("function: %s\n", mxmlElementGetAttr(function, "name"));
DEBUG_printf(" scope = %s\n", scope ? scope : "(null)");
DEBUG_printf(" comment = %p\n", comment);
DEBUG_printf(" child = (%p) %s\n", mxmlGetFirstChild(comment), get_nth_text(comment, 0, NULL));
Expand Down Expand Up @@ -3554,15 +3608,21 @@ scan_file(filebuf_t *file, /* I - File to scan */

if (typedefnode)
{
mxmlElementSetAttr(typedefnode, "name", str);
if (nsname)
mxmlElementSetAttrf(typedefnode, "name", "%s::%s", nsname, str);
else
mxmlElementSetAttr(typedefnode, "name", str);

sort_node(tree, typedefnode);
}

if (structclass && !mxmlElementGetAttr(structclass, "name"))
{
DEBUG_printf("setting struct/class name to \"%s\".\n", get_nth_text(type, -1, NULL));
mxmlElementSetAttr(structclass, "name", str);
if (nsname)
mxmlElementSetAttrf(structclass, "name", "%s::%s", nsname, str);
else
mxmlElementSetAttr(structclass, "name", str);

sort_node(tree, structclass);
structclass = NULL;
Expand All @@ -3585,7 +3645,10 @@ scan_file(filebuf_t *file, /* I - File to scan */
DEBUG_printf("Typedef: <<<< %s >>>\n", str);

typedefnode = mxmlNewElement(MXML_NO_PARENT, "typedef");
mxmlElementSetAttr(typedefnode, "name", str);
if (nsname)
mxmlElementSetAttrf(typedefnode, "name", "%s::%s", nsname, str);
else
mxmlElementSetAttr(typedefnode, "name", str);
mxmlDelete(mxmlGetFirstChild(type));

sort_node(tree, typedefnode);
Expand Down Expand Up @@ -3618,7 +3681,10 @@ scan_file(filebuf_t *file, /* I - File to scan */
break;
}

mxmlNewText(type, child != NULL && *string != '(' && *string != '*', str);
if (nsname && !fstructclass && !tree_is_scu)
mxmlNewTextf(type, child != NULL && *string != '(' && *string != '*', "%s::%s", nsname, str);
else
mxmlNewText(type, child != NULL && *string != '(' && *string != '*', str);

DEBUG_printf("Variable: <<<< %s >>>>\n", str);
DEBUG_printf(" scope = %s\n", scope ? scope : "(null)");
Expand Down Expand Up @@ -3647,7 +3713,10 @@ scan_file(filebuf_t *file, /* I - File to scan */
DEBUG_printf("Constant: <<<< %s >>>\n", str);

constant = mxmlNewElement(MXML_NO_PARENT, "constant");
mxmlElementSetAttr(constant, "name", str);
if (nsname)
mxmlElementSetAttrf(constant, "name", "%s::%s", nsname, str);
else
mxmlElementSetAttr(constant, "name", str);
sort_node(enumeration, constant);
}
else if (type)
Expand Down
18 changes: 0 additions & 18 deletions codedoc.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
<xsd:element name="enumeration" type="enumerationType"/>
<xsd:element name="function" type="functionType"/>
<xsd:element name="mxmldoc" type="mxmldocType"/>
<xsd:element name="namespace" type="namespaceType"/>
<xsd:element name="returnvalue" type="returnvalueType"/>
<xsd:element name="seealso" type="identifierList"/>
<xsd:element name="struct" type="structType"/>
Expand Down Expand Up @@ -86,30 +85,13 @@
<xsd:element ref="class"/>
<xsd:element ref="enumeration"/>
<xsd:element ref="function"/>
<xsd:element ref="namespace"/>
<xsd:element ref="struct"/>
<xsd:element ref="typedef"/>
<xsd:element ref="union"/>
<xsd:element ref="variable"/>
</xsd:choice>
</xsd:complexType>

<xsd:complexType name="namespaceType">
<xsd:sequence>
<xsd:element ref="description" minOccurs="0" maxOccurs="1"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="class"/>
<xsd:element ref="enumeration"/>
<xsd:element ref="function"/>
<xsd:element ref="struct"/>
<xsd:element ref="typedef"/>
<xsd:element ref="union"/>
<xsd:element ref="variable"/>
</xsd:choice>
</xsd:sequence>
<xsd:attribute name="name" type="identifier" use="required"/>
</xsd:complexType>

<xsd:complexType name="returnvalueType">
<xsd:sequence>
<xsd:element ref="type" minOccurs="1" maxOccurs="1"/>
Expand Down
2 changes: 1 addition & 1 deletion snap/snapcraft.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: codedoc
version: 3.3
version: 3.4
summary: Code documentation utility.
description: |
Codedoc is a documentation generator that scans the specified C and C++ source
Expand Down
Loading

0 comments on commit 5fd7dfc

Please sign in to comment.