How to use Doxygen with Prolog - c

I was struggling trying to make doxygen work with prolog.
At first I was only trying to include an "external and unknown" file, but as doxygen users know, it won't print a thing if it can't find useful (documented) functions.
Searching stackoverflow for both tags gives no single answer, and so I decided to ask, even if I already solved the puzzle, so people will have a hit in case of search.
I will let this question here, as people can suggest simple workarounds, and we may learn a bit more about the subject, but I'll use it to register my own answer after some (hard) efforts. Thanks.
To explain where I did start:
My first (almost) successful approach worked fine in a program that used both C and PROLOG.
It almost worked because latter on I saw this approach would not work in a PROLOG only project.
Anyway, what I did was simply add this
INPUT = README.md groups.dox c-and-pl.c c-and-pl.pl
FILE_PATTERNS = *.pl
EXTENSION_MAPPING += pl=c
EXTRACT_ALL = YES
EXTRACT_STATIC = YES
SOURCE_BROWSER = YES
And PROLOG code would look like:
/**
* #file cpl.pl
* #ingroup GroupUnique
* #brief CPL - C calls Prolog (Prolog module)
* #cond SKIPPROLOG
*/
/* brief explanation in a normal (non-doxygen) comment */
clause(A) :-
rule(X),
test(A, X).
and(so, on).
/** #endcond */
This would work because C would create the site anyway, and PROLOG page would be just a brief, no clauses, but a link to see the complete code, with normal comments explaining the clauses.
Why this doesn't work for a pure PROLOG project? And how to do that?

My second attempt to solve it involved the creation of a new file, a copy of the original PROLOG source, but with comments in doxygen format, and converting PROLOG clauses in something C-like.
Call the source source.pl and the second copy source.dox. You would write the PROLOG program as you usually do, using doxygen before the first occurrence of each clause, atom, module, etc.
Then cp source.pl source.dox and edit source.dox converting all clauses in something like:
/**
* \file source.pl
* \ingroup GroupUnique
*/
/**
* \ingroup GroupUnique
* \brief Defining factorial module
*/
module(fatorial, [fatpl/2]);
This takes time and are prone to errors, but it was a workaround. Problem is that doxygen now lists source.pl twice. But the functions can be documented. Use this configuration:
INPUT = README.md groups.dox source.pl source.dox
You need to keep source.pl because it is there the real source to be seen. And source.dox would be more like a C header file.
Not good. The work to transform manually a source.pl into a source.dox led me to write my own compiler (well, technically a filter, that uses only lexical tokens).
The program is available open source at github:
https://github.com/drbeco/doxygenprolog
and is cited here in the official pages among other filters: doxygen helpers
And a little note here, in the official SWI-Prolog site:
SWI-Prolog news
To make doxygen work with an unknown language you need:
Install this filter in someplace PATH can find.
Edit your doxygen .cfg to have:
OPTIMIZE_OUTPUT_FOR_C = NO
INPUT = README.md groups.dox source.pl
EXTRACT_ALL = YES
EXTRACT_STATIC = YES
FILE_PATTERNS = *.pl *.prolog *.swipl
FILTER_PATTERNS = *.pl="dox4pl"
Now you can run your doxygen as you normally do with other languages.

Related

How can I check if a certain function could be indirectly called by another certain function?

Assuming that in a project written by C, there is a function named A and a function named B.
How can I verify if the function A could be in the call tree of function B? Just like B->C->D->...->A .
This question came when I was thinking about which libvirt API may invoke the qemu qmp "query-block". Since qmp "query-block" is only called by function qemuMonitorJSONQueryBlock. So this specific question becomes: How can I find which libvirt API may invoke qemuMonitorJSONQueryBlock?
I think dynamic analysis is hard to answer that question because lots of tests are required. It should be a question of static analysis. But I could find proper tools or methods to solve it. At last I summarize the question as the first paragraph.
You can try CppDepend and its code query language to create some advanced queries about the dependencies, In you case you can use a query like this one
from m in Methods
let depth0 = m.DepthOfIsUsedBy("__Globals.B()")
where depth0 >= 0 && m.SimpleName=="A" orderby depth0
select new { m, depth0 }
You can use GNU cflow utility which analyzes a collection of source files written in C programming language and outputs a graph charting dependencies between various functions
I think dynamic analysis is hard to answer that question because lots of tests are required. It should be a question of static analysis. But I could find proper tools or methods to solve it. At last I summarize the question as the first paragraph.
That's true, basically because you can call functions that you have never linked in your program. with the dlopen(3) function and friends, you can dynamically link to your program a completely unknown function and be able to call it. There's no way to check if the pointer to a function is actually storing a valid pointer and to see if, as a result, it will be called or not (or if it is in the call graph of some initial function)
I find cscope can help solve the question. It is a
is a developer's tool for browsing source code. It can get the caller of a function by following:
1. Change to the source code directory, then generate the cscope database file named cscope.out
cd libvirt
cscope -bR
Find the callers of func1 by cscope:
cscope -d -f cscope.out -L3 func1, then 2nd column is the callers of this function. For example:
cscope -d -f./cscope.out -L3 qemuMigrationDstPrepareDirect
The result:
src/qemu/qemu_driver.c ATTRIBUTE_NONNULL 12487 ret = qemuMigrationDstPrepareDirect(driver, dconn,
src/qemu/qemu_driver.c qemuDomainMigratePrepare2 12487 ret = qemuMigrationDstPrepareDirect(driver, dconn,
src/qemu/qemu_driver.c qemuDomainMigratePrepare3 12722 ret = qemuMigrationDstPrepareDirect(driver, dconn,
src/qemu/qemu_driver.c qemuDomainMigratePrepare3Params 12809 ret = qemuMigrationDstPrepareDirect(driver, dconn,
Note that: cscope will mistakenly regard function attribute declarement ATTRIBUTE_* as callers. We should skip them.
Then recursively find the caller of the a function. At last select the target B->...->A call trace.
doxygen can generate call graphs and caller graphs. If you configure it for an unlimited number of calls in a graph, you will be able to get the information you need.

Frama-c: save plugin analysis results in c file

I'am new in frama-c. So I apologize in advance for my question.
I would like to make a plugin that will modify the source code, clone some functions, insert some functions calls and I would like my plugin to generate a second file that will contain the modified version of the input file.
I would like to know if it is possible to generate a new file c with frama-c. For example, the results of the Sparecode and Semantic constant folding plugins are displayed on the terminal directly and not in a file. So I would like to know if Frama-c has the function to write to a file instead of sending the result of the analysis to the standard output.
Of course we can redirect the output of frama-c to a file.c for example, but in this case, for the plugin scf for example, the results of value is there and I found that frama-c replaces for example the "for" loops by while.
But what I would like is that frama-c can generate a file that will contain my original code plus the modifications that I would have inserted.
I looked in the directory src / kernel_services / ast_printing but I have not really found functions that can guide me.
Thanks.
On the command line, option -ocode <file> indicates that any subsequent -print will be done in <file> instead of the standard output (use -ocode "" after that if you want to print on stdout again). Note that -print prints the code corresponding to the current project. You can use -then-on <prj> to change the project you're interested in. More information is of course available in the user manual.
All of this is of course available programmatically. In particular, File.pretty_ast by defaults pretty-prints (i.e. output a C program) the AST of the current project on stdout, but takes two optional argument for changing the project or the formatter to which the output should be done.

Doxygen: Outputting Version Numbers

I would like to have Doxygen display the source code version number as part of the main page or the title header.
Presently, our code has the version defined as a text literal:
/*!
* \brief Text literal containing the build number portion of the
* ESG Application Version.
*/
static const char build_version_text[] = "105";
I have searched the internet for a method to get the 105 from the above statement into the Doxygen main page (or header) with no luck.
Background
We have a build server that updates the text string as part of a nightly build operation. The file is updated, then checked into the Software Configuration Management system. The build server is also capable of generating the documentation. We would also like to have the developers be able to check out the code, the build the Doxygen documentation at their workstations.
We are using Doxygen version 1.8.11.
What you're looking for is to set the PROJECT_NUMBER config option based on the value in your source. I don't think this can be done, but the way I would go about achieving the same result is as follows.
Since the project version is updated when a build script runs, have the build script generate an extra file, for example Doxyversion. Have the content of the file be:
PROJECT_NUMBER = "<versiontext>"
Update your main Doxyfile and replace
PROJECT_NUMBER =
with
#INCLUDE = "<pathToDoxyversion>"
Edit:
A solution I can think of that does not require duplicating the version string requires parsing the version string out from the file into an environment variable. Then you can set PROJECT_NUMBER to
PROJECT_NUMBER=$(ENV_VAR)
Another option is you can call doxygen with
( cat Doxyfile ; echo "PROJECT_NUMBER=$ENV_VAR" ) | doxygen
Both solutions would require the developers to know to do this when generating the documentation, or wrapping the entire doxygen call in a script. Also potential portability issues.
Full solution below, from a real example.
Main page
In the documentation for the main page (or anywhere, really), use special markers for the text to substitute dynamically.
Main page source:
https://github.com/mysql/mysql-server/blob/8.0/sql/mysqld.cc#L22
See the special ${DOXYGEN_GENERATION_DATE} markers
Doxygen input filters
In the doxygen configuration file, define an input filter for the file containing the special markers. For example,
FILTER_PATTERNS = "*/sql/mysqld.cc=./doxygen-filter-mysqld"
Implement the doxygen-filter-mysqld script to:
Find the dynamic value to substitute (in your case, parse the value of build_version_text)
Replace (sed) the special marker with the value
Output the result to stdout
For example:
CMD1="s/\\\${DOXYGEN_GENERATION_DATE}/"`date -I`"/g"
...
sed -e ${CMD1} -e ${CMD2} -e ${CMD3} $1
Results
Result is at
http://devdocs.no.oracle.com/mysql-server/8.0.0/
See Also
All this is a work around for that I think should be a good Doxygen feature.
See bug#769679 (Feature Request: doxygen command to expand an environment variable) that was entered for this.
https://bugzilla.gnome.org/show_bug.cgi?id=769679

Using lint comments with doxygen

For documentation, we usually have to create an additional document describing what we did when any lint messages were disabled in code (e.g. /* lint --e228).
It would make it much easier to use it with doxygen (as we create this anyhow).
Though, I wasn't able to find any solution on how to make doxygen using these lint comments.
Did anyone try this?
Is there any solution how to use the stric '/*lint' but anyhow add it to doxygen?
Thanks!
This can be accomplished by defining a macro to expand into the lint expression comment, but making the macro expand into a different comment when expanded by doxygen.
The trick is to use the -save instruction to PC-lintTM or FlexeLintTM:
#ifndef LINT_CONTROL
#define LINT_CONTROL(X) /*lint -save X */ //lint X
#endif
int main () {
int a; LINT_CONTROL(-e530)
return a != a;
}
Then, in your doxygen configuration file, you can enable expansion of certain preprocessor macros. In particular, we can change LINT_CONTROL to expand into a doxygen-ated comment instead.
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = "LINT_CONTROL(X)=//! lint control: X"
Alternatively, if you have FlexeLintTM, then you can modify the shrouded source so that a doxygen comment can be used to trigger the lint control. The technique is described on the Gimpel Software Discussion Forum. (This link seems dead, and the new discussion forum seems to no longer contain the referenced discussion any longer.)
PC-lint and FlexeLint are trademarks of Gimpel Software.

Configure Doxygen to hide certain names or keywords

I'm just getting started with Doxygen, and have done considerable searching on this, so forgive me if there's an obvious answer.
I'm working on an embedded project where functions can be tagged as debug or nodebug before the return type. In most of our libraries, we use a conditional macro to set libname_debug to either debug or nodebug at the top of the file, and then each function is prefaced with libname_debug.
For documentation purposes, I'd like to have Doxygen leave libname_debug out of the function documentation. It clutters up the function list and makes it harder to see the return types of each function.
Is it possible to tag the file in some way so Doxygen will leave that symbol out? At the moment, I'm wrapping each instance in #cond/#endcond:
/** #cond */ libname_debug /** #endcond */
But that's a pain and adds extra markup to the source.
There is also a doxygen page explaining how to handle such situations. You would enable MACRO_EXPANSION (which defaults to NO), tell doxygen to only expand some macros (EXPAND_ONLY_PREDEF) and add your symbol as macro with an empty expansion:
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
PREDEFINED = libname_debug=
You can define macros in the doxygen configuration file. Something like this
PREDEFINED += libname_debug

Resources