[C2HELP]
* NEW: Scripts to generate Gambas documentation files from C/C++ sources git-svn-id: svn://localhost/gambas/trunk@6712 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
parent
a213747294
commit
ea6578d19b
7 changed files with 309 additions and 0 deletions
113
c2help/README
Normal file
113
c2help/README
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
About c2help
|
||||||
|
------------
|
||||||
|
|
||||||
|
c2help is used to extract Gambas documentation from C/C++ source files and
|
||||||
|
create .help files for a component from them.
|
||||||
|
|
||||||
|
Project compass
|
||||||
|
---------------
|
||||||
|
|
||||||
|
./extract.awk -- Extract help comments
|
||||||
|
./xlate.sh -- Translate C/C++ function names to Gambas symbol names
|
||||||
|
./prefix.awk -- Prefix symbol names with the classes they belong to
|
||||||
|
./mkhelp.gbs3 -- Create a .help file from the (properly formatted) input
|
||||||
|
|
||||||
|
./c2help.sh -- Executes the above programs in the correct order to create
|
||||||
|
the .help in a number of C/C++ sources.
|
||||||
|
|
||||||
|
... and why?
|
||||||
|
------------
|
||||||
|
|
||||||
|
Components written in Gambas can already be documented in-code. This docu-
|
||||||
|
mentation is then stored inside their .info files. With a similar result
|
||||||
|
provided by c2help for C/C++ components, we can document all[*] Gambas in
|
||||||
|
its source files (at least my components will be) which makes it, IMHO,
|
||||||
|
easier to keep the documentation up-to-date. Also the help could be
|
||||||
|
displayed locally by the IDE or remotely once these .help files are imported
|
||||||
|
to the gambaswiki.org site.
|
||||||
|
|
||||||
|
Also, documentation can be bound to a specific source code version, so that
|
||||||
|
you get docs for the version of Gambas you are running, not only for the
|
||||||
|
development branch.
|
||||||
|
|
||||||
|
[*] I'm not sure about intrinsic functions, though. Should be feasible,
|
||||||
|
looking at gbx_class_info.c...
|
||||||
|
|
||||||
|
Great! How do I prepare my component?
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
The No 0 rule is to BE CAREFUL! There are quite some rules to remember:
|
||||||
|
|
||||||
|
1. Documentation syntax.
|
||||||
|
|
||||||
|
You may write a Gambas documentation comment like
|
||||||
|
|
||||||
|
/**G
|
||||||
|
* Here goes the documentation.
|
||||||
|
**/
|
||||||
|
BEGIN_METHOD_VOID(ClassName_MethodName)
|
||||||
|
/* ... */
|
||||||
|
END_METHOD
|
||||||
|
|
||||||
|
or alternatively
|
||||||
|
|
||||||
|
/**G Class Symbol
|
||||||
|
* Documenting Class.Symbol
|
||||||
|
**/
|
||||||
|
|
||||||
|
Instead of the **/ at the end, you may also write */. Cool, huh?
|
||||||
|
|
||||||
|
The difference between both notations is that the first must immediately
|
||||||
|
precede a BEGIN_{PROPERTY,METHOD,METHOD_VOID) line that defines the symbol
|
||||||
|
to which the documentation refers. The second syntax documents the indicated
|
||||||
|
symbol -- no matter where the comment is.
|
||||||
|
|
||||||
|
This is intended to document GB_CONSTANTs or GB_PROPERTY_SELFs which don't
|
||||||
|
have a BEGIN_* line. It can neverthelss be used for any other symbol but
|
||||||
|
NEVER intermix both syntaxes on a single symbol.
|
||||||
|
|
||||||
|
The ClassName_MethodName part I call "(implementation) function name". The
|
||||||
|
particular format shown is not mandatory. The scripts take the function name
|
||||||
|
and look up the corresponding symbol in your GB_DESC[].
|
||||||
|
|
||||||
|
2. Strict regular expressions.
|
||||||
|
|
||||||
|
The regular expressions used to filter these comments are somewhat strict.
|
||||||
|
You have to pass the spaces exactly as indicated in the line where you
|
||||||
|
comment text starts, i.e. <space>*<space>text. Also note that Class and
|
||||||
|
Symbol in the second syntax are case sensitive!
|
||||||
|
|
||||||
|
3. Strict structure.
|
||||||
|
|
||||||
|
Really. The next empty-or-not line after a syntax-1 help block is taken as
|
||||||
|
the symbol definition line. If it's not, you get a wrong symbol name.
|
||||||
|
|
||||||
|
DON'T try to confuse the parsers by not giving information it needs where
|
||||||
|
it expects it.
|
||||||
|
|
||||||
|
4. Synonyms.
|
||||||
|
|
||||||
|
The first match for a function name lookup in a GB_DESC[] is taken as the
|
||||||
|
"primary" implementation of that symbol. That means the help comment will
|
||||||
|
be attched to that symbol. All other symbols which call the same function
|
||||||
|
are considered synonyms and are *automatically* documented with the default
|
||||||
|
sentence: "This is a synonym for <primary-symbol>". DO NOT document them
|
||||||
|
separately using a syntax-2 help block!
|
||||||
|
|
||||||
|
5. Don't reuse method and property implementations (except for synonyms).
|
||||||
|
|
||||||
|
As the implementation function name is searched in the GB_DESC[]s in your
|
||||||
|
source file, you may not put the same function into different classes -- or
|
||||||
|
the parser may get confused.
|
||||||
|
|
||||||
|
Umm... I need an example
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
gb.openssl and gb.data are partially documented that way. Digest.Hash() and
|
||||||
|
Digest._call() in gb.openssl show how to deal with synonyms. There the entry
|
||||||
|
for Hash precedes the entry for _call, thus Hash is the primary symbol and
|
||||||
|
_call a synonym.
|
||||||
|
|
||||||
|
To see a sample .help file (on stdout), you can do at the source tree root:
|
||||||
|
|
||||||
|
$ c2help/c2help.sh gb.openssl
|
1
c2help/TODO
Normal file
1
c2help/TODO
Normal file
|
@ -0,0 +1 @@
|
||||||
|
- Class documentation. Shouldn't be too difficult.
|
27
c2help/c2help.sh
Executable file
27
c2help/c2help.sh
Executable file
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ $# -lt 1 ]
|
||||||
|
then cat >&2 <<EOF
|
||||||
|
|
||||||
|
Usage: $0 SOURCES...
|
||||||
|
|
||||||
|
Extract Gambas help comments from all SOURCES and output a .help file.
|
||||||
|
If SOURCES contains directories, they are searched recursively for .c
|
||||||
|
and .cpp files.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
function doit {
|
||||||
|
for arg in ${@:1}
|
||||||
|
do echo Processing $arg... >&2
|
||||||
|
if [ -d "$arg" ]
|
||||||
|
then doit $(find -H $arg -name \*.c -or -name \*.cpp)
|
||||||
|
else $(dirname $0)/extract.awk <$arg | sed "s/^[ ]*\*/\'/" |
|
||||||
|
$(dirname $0)/xlate.sh $arg | $(dirname $0)/mkhelp.gbs3
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
doit ${@:1}
|
72
c2help/extract.awk
Executable file
72
c2help/extract.awk
Executable file
|
@ -0,0 +1,72 @@
|
||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
# Extract comments from C/C++ source files (stdin)
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
do_record = 0;
|
||||||
|
not_this = 0;
|
||||||
|
symname = "";
|
||||||
|
FS="";
|
||||||
|
}
|
||||||
|
|
||||||
|
/^[\t ]*\*?\*\/$/ {
|
||||||
|
if (length(symname)) {
|
||||||
|
print "G "symname "\n";
|
||||||
|
do_record = 0;
|
||||||
|
}
|
||||||
|
not_this = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/^BEGIN\_.*\(.*/ {
|
||||||
|
if (do_record && length(symname) == 0) {
|
||||||
|
s = gensub(/^BEGIN\_.*\(([^,)]+).*/, "\\1", "");
|
||||||
|
if (length(s) == 0)
|
||||||
|
print "ERROR\n";
|
||||||
|
else
|
||||||
|
print s "\n";
|
||||||
|
do_record = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if (do_record && !not_this)
|
||||||
|
print gensub(/^[\t ]*/, " ", "");
|
||||||
|
not_this = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# The 'G' flag is important to distinguish intended Gambas documentation
|
||||||
|
# for the wiki (*.help files) and already existing C function commentary.
|
||||||
|
#
|
||||||
|
# The start marker may either be:
|
||||||
|
#
|
||||||
|
# ^/**G$ # Note that this describes an *entire* line
|
||||||
|
#
|
||||||
|
# when it preceeds a symbol definition (BEGIN_*) or alternatively
|
||||||
|
#
|
||||||
|
# /**G Class Symbol$ # Here, only the end of line matters
|
||||||
|
#
|
||||||
|
# if it documents the Gambas symbol "Symbol" in "Class". This is intended
|
||||||
|
# for documentation of symbols that are not to be implemented in something
|
||||||
|
# that begins with BEGIN_*, like GB_CONSTANTs or GB_PROPERTY_SELFs. It can
|
||||||
|
# also be used for any other symbol type but both documentation types should
|
||||||
|
# not be used together on a single symbol.
|
||||||
|
|
||||||
|
/^\/\*\*G$/ {
|
||||||
|
if (do_record)
|
||||||
|
print "ERROR\n";
|
||||||
|
symname = "";
|
||||||
|
do_record = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/[\t ]*\/\*\*G .+$/ {
|
||||||
|
if (do_record)
|
||||||
|
print "ERROR\n";
|
||||||
|
symname = gensub(/\/\*\*G (.*)$/, "\\1", "");
|
||||||
|
gsub(/^[\t ]*/, "", symname);
|
||||||
|
do_record = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
if (do_record)
|
||||||
|
print "ERROR\n";
|
||||||
|
}
|
42
c2help/mkhelp.gbs3
Executable file
42
c2help/mkhelp.gbs3
Executable file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/gbs3
|
||||||
|
|
||||||
|
Private $cHelp As New Collection
|
||||||
|
Private $aCurrent As New String[]
|
||||||
|
|
||||||
|
Public Sub Main()
|
||||||
|
Dim sLine As String
|
||||||
|
Dim cClass As Collection, aHelp, aSyn As String[]
|
||||||
|
Dim iInd As Integer
|
||||||
|
|
||||||
|
For Each sLine in File.In.Lines
|
||||||
|
If Not sLine Then Continue
|
||||||
|
If sLine Begins "'" Then
|
||||||
|
$aCurrent.Add(sLine)
|
||||||
|
Else
|
||||||
|
With Scan(sLine, "* *") ' <Class> <Symbol-and-Synonym-List>
|
||||||
|
.[0] = Trim$(.[0])
|
||||||
|
.[1] = Trim$(.[1])
|
||||||
|
If .Count <> 2 Then
|
||||||
|
Error "Skipping malformed line:";; sLine
|
||||||
|
Continue
|
||||||
|
Endif
|
||||||
|
If Not $cHelp[.[0]] Then $cHelp[.[0]] = New Collection
|
||||||
|
$cHelp[.[0]][.[1]] = $aCurrent
|
||||||
|
$aCurrent = New String[]
|
||||||
|
End With
|
||||||
|
Endif
|
||||||
|
Next
|
||||||
|
|
||||||
|
For Each cClass In $cHelp
|
||||||
|
Print "#"; $cHelp.Key
|
||||||
|
For Each aHelp In cClass
|
||||||
|
aSyn = Split(cClass.Key, " ")
|
||||||
|
Print aSyn[0]
|
||||||
|
If aHelp.Count Then Print aHelp.Join("\n")
|
||||||
|
For iInd = 1 To aSyn.Max
|
||||||
|
Print aSyn[iInd]
|
||||||
|
Print "' A synonym for";; aSyn[0]; "."
|
||||||
|
Next
|
||||||
|
Next
|
||||||
|
Next
|
||||||
|
End
|
16
c2help/prefix.awk
Executable file
16
c2help/prefix.awk
Executable file
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/gawk -f
|
||||||
|
|
||||||
|
BEGIN {
|
||||||
|
class = "ERROR";
|
||||||
|
}
|
||||||
|
|
||||||
|
/GB_DECLARE/ {
|
||||||
|
class = gensub(/GB_DECLARE\("([^"]+).*/, "\\1", "");
|
||||||
|
gsub(/[\t ]+/, "", class);
|
||||||
|
}
|
||||||
|
|
||||||
|
match($0, "GB_.*" funcname) {
|
||||||
|
printf class " ";
|
||||||
|
# Only print once as there may be synonyms.
|
||||||
|
exit;
|
||||||
|
}
|
38
c2help/xlate.sh
Executable file
38
c2help/xlate.sh
Executable file
|
@ -0,0 +1,38 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Translate C/C++ function name to Gambas symbol name
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]
|
||||||
|
then cat >&2 <<EOF
|
||||||
|
|
||||||
|
Usage: $0 CLASSDEF
|
||||||
|
|
||||||
|
Translate C/C++ function names (from stdin) to Gambas symbol
|
||||||
|
names using the class definition in the CLASSDEF file.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while read line
|
||||||
|
do if [ -z "$line" -o "$line" == "NULL" ]
|
||||||
|
then echo $line
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ $line == \'* ]]
|
||||||
|
# Quoting is important here to not lose whitespace
|
||||||
|
then echo "$line"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# It's the symbol name already (a syntax-2 help block)?
|
||||||
|
if [[ $line =~ ^G[\ ] ]]
|
||||||
|
then echo "$line" | sed 's/^G //'
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# Now, we have a C/C++ function name in $line. First search the class.
|
||||||
|
$(dirname $0)/prefix.awk -v funcname=$line <$1
|
||||||
|
# Put all the synonyms behind.
|
||||||
|
egrep "GB_.*$line[,)]" $1 | sed 's/^[\t]*GB_[^(]\+("\([^"]\+\)".*$/\1/' |
|
||||||
|
tr '\n' ' '
|
||||||
|
done
|
Loading…
Reference in a new issue