Doxygen are not collecting all \todo in global todo list - c

I have a problem with doxygen. Not all my \todo are collected in the global todo list, but most of them. I have made a simple C-example with a single source and header file, as well as a configuration file, where i have placed todos everywhere i want doxygen to collect them into the global todo list.
My global todo list is missing the shown todos in the below code snippet, meaning the one inside the body of my public function (test_todo12 in myFunc), as well as the ones in the cfg file (test_todo16 and test_todo17), both implemented as shown below.
test.h:
/**
* Definition of test structure.
*/
typedef struct def_struct_
{
int32_t first; /**< First element.*/
int32_t second; /**< Second element. */
int32_t third; /**< third element. */
} def_struct_t;
/**************************************************************************************************/
/**
* \brief My func description.
*
* \param[ in ] test_param Input parameter to myFunc.
*
* \return bool
* \retval false false on non success.
* \retval true true on success.
*
**************************************************************************************************/
bool myFunc( uint32_t test_param );
test.c:
#include <stdint.h>
#include <stdbool.h>
#include "test.h"
#include "test.cfg"
bool myFunc( uint32_t test_param )
{
uint32_t testVar = test_param ;
//! This function does nothing. \todo test_todo12
testVar++;
return true;
}
test.cfg:
/** test cfg
* \todo test_todo16
*/
static def_struct_t test_cfg[2] =
{
.first = 123 //! \todo test_todo17
}
I am using doxygen version 1.8.14
The differences in my doxygen configuration file compared to the default settings are the following (after trying alot of different combinations):
OPTIMIZE_OUTPUT_FOR_C = YES
TOC_INCLUDE_HEADINGS = 1
TYPEDEF_HIDES_STRUCT = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
INTERNAL_DOCS = YES
HIDE_SCOPE_NAMES = YES
WARN_NO_PARAMDOC = YES
RECURSIVE = YES
EXCLUDE_PATTERNS = */README.md
EXAMPLE_RECURSIVE = YES
SOURCE_BROWSER = YES
GENERATE_TREEVIEW = YES
USE_MATHJAX = YES
GENERATE_LATEX = NO
CLASS_DIAGRAMS = NO
HAVE_DOT = YES
UML_LOOK = YES
DOT_PATH = "C:\Program Files (x86)\Graphviz2.38\lib\release\lib"
DOTFILE_DIRS = "C:\Program Files (x86)\Graphviz2.38\lib\release\lib" \ "C:\Program Files (x86)\Graphviz2.38\bin"
PLANTUML_JAR_PATH = C:\tools\plantUML
and added *.cfg \ to FILE_PATTERNS
Link to the full compilable code and doxygen configuration (minimal example for showing this problem): Link to code
When i navigate to the public function "myFunc" i see the todo, it is just missing in the global todo list.
The cfg file does not seem to be included in the doxygen documentation at all, event though it is included in the C file, and theby should be seen as a part of this file? Or is it really necessary to do something extra/special for including these cfg files? If so, does someone know what I am missing?
I hope someone can help me solve my problem, maybe the todo in the public function body is even a bug?
Regards
Jesper

Looks like there are a number of issues here.
the extension cfg is not known to doxygen and only adding it to FILE_PATTERNS is not sufficient, also the language in which it is written has to be made known to doxygen, so EXTENSION_MAPPING = cfg=C.
the variable in the test.cfg is missing a semi-colon (;) at the end. last line should read };
the comment inside the initialization is not considered by doxygen as documenting something (also in the current version 1.8.16 this is not considered). Problem would be where does it belong, for a \todo is would be clear that it can land on the ToDo page, but should it also land with the variable itself? and how about other comments (initializations are now variables). As a side note when using STRIP_CODE_COMMENTS=NO the comment is not shown in the initialization either.

Related

Using C to modify response in VCL

The varnish docs say that we can include C snippets inside a VCL file, like
sub vcl_hash {
C{
int i = /* Some logic to get a number */
}C
}
But now how can I use the value of the integer i to set a response header, or cookie
See varnish.vcc
And the functions:
VRT_SetHdr
VRT_GetHdr
in varnish 4 there is ctx variabl defined for the context (as opposed to sp in varnish 3 ) (source)
example:
sub vcl_hash {
C{
const char *hash = calc_hash(...);
const struct gethdr_s hdr = {
HDR_BERESP,
"\010X-Hash:" // length prefixed string, in octal
};
VRT_SetHdr(ctx, &hdr, hash, vrt_magic_string_end);
}C
}
see here for another example
Why don't you just use VCL?
set resp.http.x-header = header to set any header you wanna set.
I'd encourage you to write a vmod directly, It'll be way more comfortable. You can find a (old but still relevant) guide here: https://info.varnish-software.com/blog/creating-a-vmod-vmod-str

undefined reference to function that is already defined

Currently trying to build a project in eclipse. The project explorer is shown below:
In cabbie.c I get the error, undefined reference to initialize..., in the code below:
#include <stdio.h>
#include <stdlib.h>
#include "../iotfclient.h"
Iotfclient client;
int rc;
int main() {
/* Setup your example here, code that should run once
*/
rc = initialize(&client, "h7dzt2", "Edison_cabquam", "notwindows95", "token", "Over_9000");
/* Code in this loop will run repeatedly
*/
for (;;) {
}
return 0;
}
The function is already defined in iotfclient.h which was included as a header file. Is it correct to define it as ../iotfclient.h? Am I supposed to make a Makefile? The function prototype in iotfclient.h is given below:
int initialize(Iotfclient *client, char *orgId, char *deviceType, char *deviceId, char *authmethod, char *authtoken);
/**
* Function used to initialize the IBM Watson IoT client using the config file which is generated when you register your device
* #param client - Reference to the Iotfclient
* #param configFilePath - File path to the configuration file
*
* #return int return code
* error codes
* CONFIG_FILE_ERROR -3 - Config file not present or not in right format
*/
This project is trying to connect the bluemix IOT Platform.
initialize() is declared in iotfclient.h. However, it's not necessary defined. In other words, the compiler knows identifier initialise stands for a function, but to create a program, you have also to tell the linker how the function works, that is, add the function body.
Try including ../iotfclient.c.
The function initialize is declared in ../iotfclient.h, it might be defined in ../iotfclient.c, but do you compile this file and link it to your project?

How do you get the start and end addresses of a custom ELF section?

I'm working in C on Linux. I've seen the usage of of the gcc __section__ attribute (especially in the Linux kernel) to collect data (usually function pointers) into custom ELF sections. How is the "stuff" that gets put in those custom sections retrieved and used?
As long as the section name results in a valid C variable name, gcc (ld, rather) generates two magic variables: __start_SECTION and __stop_SECTION. Those can be used to retrieve the start and end addresses of a section, like so:
/**
* Assuming you've tagged some stuff earlier with:
* __attribute((__section__("my_custom_section")))
*/
struct thing *iter = &__start_my_custom_section;
for ( ; iter < &__stop_my_custom_section; ++iter) {
/* do something with *iter */
}
I couldn’t find any formal documentation for this feature, only a few obscure mailing list references. If you know where the docs are, drop a comment!
If you're using your own linker script (as the Linux kernel does) you'll have to add the magic variables yourself (see vmlinux.lds.[Sh] and this SO answer).
See here for another example of using custom ELF sections.
Collecting the information together from various answers, here is a working example of how to collect information into a custom linker section and then read the information from that section using the magic variables __start_SECTION and __stop_SECTION in your C program, where SECTION is the name of the section in the link map.
The __start_SECTION and __stop_SECTION variables are made available by the linker so explicit extern references need to be created for these variables when they are used from C code.
There are also some problems if the alignment used by the compiler for calculating pointer/array offsets is different than the alignment of the objects packed in each section by the linker. One solution (used in this example) is to store only a pointer to the data in the linker section.
#include <stdio.h>
struct thing {
int val;
const char* str;
int another_val;
};
struct thing data1 = {1, "one"};
struct thing data2 = {2, "two"};
/* The following two pointers will be placed in "my_custom_section".
* Store pointers (instead of structs) in "my_custom_section" to ensure
* matching alignment when accessed using iterator in main(). */
struct thing *p_one __attribute__((section("my_custom_section"))) = &data1;
struct thing *p_two __attribute__((section("my_custom_section"))) = &data2;
/* The linker automatically creates these symbols for "my_custom_section". */
extern struct thing *__start_my_custom_section;
extern struct thing *__stop_my_custom_section;
int main(void) {
struct thing **iter = &__start_my_custom_section;
for ( ; iter < &__stop_my_custom_section; ++iter) {
printf("Have thing %d: '%s'\n", (*iter)->val, (*iter)->str);
}
return 0;
}
Linker can use the symbols defined in the code, and can assign their initial values if you use the exact name in the linker script:
_smysection = .;
*(.mysection)
*(.mysection*)
_emysection = .;
Just define a variable in C code:
const void * _smysection;
And then you can access that as a regular variable.
u32 someVar = (u32)&_smysection;
So the answer above, __start_SECTION and __stop_SECTION will work, however for the program to be able to use the information from the linker you to need to declare those variables as extern char* __start_SECTION. Enjoy!
extern char * __start_blobby;
...
printf("This section starts at %p\n", (unsigned int)&__start_blobby);
...
HI: like this.
extern const struct pseudo_ta_head __start_ta_head_section;
extern const struct pseudo_ta_head __stop_ta_head_section;
const struct pseudo_ta_head *start = &__start_ta_head_section;
const struct pseudo_ta_head *end = &__stop_ta_head_section;

get function address from name [.debug_info ??]

I was trying to write a small debug utility and for this I need to get the function/global variable address given its name. This is built-in debug utility, which means that the debug utility will run from within the code to be debugged or in plain words I cannot parse the executable file.
Now is there a well-known way to do that ? The plan I have is to make the .debug_* sections to to be loaded into to memory [which I plan to do by a cheap trick like this in ld script]
.data {
*(.data)
__sym_start = .;
(debug_);
__sym_end = .;
}
Now I have to parse the section to get the information I need, but I am not sure this is doable or is there issues with this - this is all just theory. But it also seems like too much of work :-) is there a simple way. Or if someone can tell upfront why my scheme will not work, it ill also be helpful.
Thanks in Advance,
Alex.
If you are running under a system with dlopen(3) and dlsym(3) (like Linux) you should be able to:
char thing_string[] = "thing_you_want_to_look_up";
void * handle = dlopen(NULL, RTLD_LAZY | RTLD_NOLOAD);
// you could do RTLD_NOW as well. shouldn't matter
if (!handle) {
fprintf(stderr, "Dynamic linking on main module : %s\n", dlerror() );
exit(1);
}
void * addr = dlsym(handle, thing_string);
fprintf(stderr, "%s is at %p\n", thing_string, addr);
I don't know the best way to do this for other systems, and this probably won't work for static variables and functions. C++ symbol names will be mangled, if you are interested in working with them.
To expand this to work for shared libraries you could probably get the names of the currently loaded libraries from /proc/self/maps and then pass the library file names into dlopen, though this could fail if the library has been renamed or deleted.
There are probably several other much better ways to go about this.
edit without using dlopen
/* name_addr.h */
struct name_addr {
const char * sym_name;
const void * sym_addr;
};
typedef struct name_addr name_addr_t;
void * sym_lookup(cost char * name);
extern const name_addr_t name_addr_table;
extern const unsigned name_addr_table_size;
/* name_addr_table.c */
#include "name_addr.h"
#define PREMEMBER( X ) extern const void * X
#define REMEMBER( X ) { .sym_name = #X , .sym_addr = (void *) X }
PREMEMBER(strcmp);
PREMEMBER(printf);
PREMEMBER(main);
PREMEMBER(memcmp);
PREMEMBER(bsearch);
PREMEMBER(sym_lookup);
/* ... */
const name_addr_t name_addr_table[] =
{
/* You could do a #include here that included the list, which would allow you
* to have an empty list by default without regenerating the entire file, as
* long as your compiler only warns about missing include targets.
*/
REMEMBER(strcmp),
REMEMBER(printf),
REMEMBER(main),
REMEMBER(memcmp),
REMEMBER(bsearch),
REMEMBER(sym_lookup);
/* ... */
};
const unsigned name_addr_table_size = sizeof(name_addr_table)/sizeof(name_addr_t);
/* name_addr_code.c */
#include "name_addr.h"
#include <string.h>
void * sym_lookup(cost char * name) {
unsigned to_go = name_addr_table_size;
const name_addr_t *na = name_addr_table;
while(to_to) {
if ( !strcmp(name, na->sym_name) ) {
return na->sym_addr;
}
na++;
to_do--;
}
/* set errno here if you are using errno */
return NULL; /* Or some other illegal value */
}
If you do it this way the linker will take care of filling in the addresses for you after everything has been laid out. If you include header files for all of the symbols that you are listing in your table then you will not get warnings when you compile the table file, but it will be much easier just to have them all be extern void * and let the compiler warn you about all of them (which it probably will, but not necessarily).
You will also probably want to sort your symbols by name such that you can use a binary search of the list rather than iterate through it.
You should note that if you have members in the table which are not otherwise referenced by the program (like if you had an entry for sqrt in the table, but didn't call it) the linker will then want (need) to link those functions into your image. This can make it blow up.
Also, if you were taking advantage of global optimizations having this table will likely make those less effective since the compiler will think that all of the functions listed could be accessed via pointer from this list and that it cannot see all of the call points.
Putting static functions in this list is not straight forward. You could do this by changing the table to dynamic and doing it at run time from a function in each module, or possibly by generating a new section in your object file that the table lives in. If you are using gcc:
#define SECTION_REMEMBER(X) \
static const name_addr_t _name_addr##X = \
{.sym_name= #X , .sym_addr = (void *) X } \
__attribute__(section("sym_lookup_table" ) )
And tack a list of these onto the end of each .c file with all of the symbols that you want to remember from that file. This will require linker work so that the linker will know what to do with these members, but then you can iterate over the list by looking at the begin and end of the section that it resides in (I don't know exactly how to do this, but I know it can be done and isn't TOO difficult). This will make having a sorted list more difficult, though. Also, I'm not entirely certain initializing the .sym_name to a string literal's address would not result in cramming the string into this section, but I don't think it would. If it did then this would break things.
You can still use objdump to get a list of the symbols that the object file (probably elf) contains, and then filter this for the symbols you are interested in, and then regenerate the table file the table's members listed.

unix DECLARE_WAIT_QUEUE_HEAD (var) var prototype?

i want to work with 2 queue in the module where i change my pointer to them
therefore i need to use :
//declartion
wait_queue_head_t **currentQ;
DECLARE_WAIT_QUEUE_HEAD (readWaitQ1);
DECLARE_WAIT_QUEUE_HEAD (readWaitQ2);
if(condition){
currentQ = &readWaitQ1;
}else{
currentQ = &readWaitQ2;
}
but i get incorrect type for wake_up an other stuff using the queue.
even thought i google it i couldnt find an answer can someone just give me the prototype needed?...
Since the macro is (see here):
#define DECLARE_WAIT_QUEUE_HEAD(name) \
wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
that means that:
DECLARE_WAIT_QUEUE_HEAD (readWaitQ1);
translates to:
wait_queue_head_t readWaitQ1 = ...;
Now with your current code:
wait_queue_head_t **currentQ;
currentQ = &readWaitQ1;
you have one too many indirections on currentQ. You should try:
wait_queue_head_t *currentQ;
instead.

Resources