diff --git a/c2help/README b/c2help/README new file mode 100644 index 000000000..9031db196 --- /dev/null +++ b/c2help/README @@ -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. *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 ". 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 diff --git a/c2help/TODO b/c2help/TODO new file mode 100644 index 000000000..9973f24f2 --- /dev/null +++ b/c2help/TODO @@ -0,0 +1 @@ + - Class documentation. Shouldn't be too difficult. diff --git a/c2help/c2help.sh b/c2help/c2help.sh new file mode 100755 index 000000000..14576918e --- /dev/null +++ b/c2help/c2help.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +if [ $# -lt 1 ] + then cat >&2 <&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} diff --git a/c2help/extract.awk b/c2help/extract.awk new file mode 100755 index 000000000..a6ad64823 --- /dev/null +++ b/c2help/extract.awk @@ -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"; +} diff --git a/c2help/mkhelp.gbs3 b/c2help/mkhelp.gbs3 new file mode 100755 index 000000000..d753151f9 --- /dev/null +++ b/c2help/mkhelp.gbs3 @@ -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, "* *") ' + .[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 diff --git a/c2help/prefix.awk b/c2help/prefix.awk new file mode 100755 index 000000000..fb11f91a4 --- /dev/null +++ b/c2help/prefix.awk @@ -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; +} diff --git a/c2help/xlate.sh b/c2help/xlate.sh new file mode 100755 index 000000000..993e1db3b --- /dev/null +++ b/c2help/xlate.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Translate C/C++ function name to Gambas symbol name + +if [ $# -ne 1 ] + then cat >&2 <