Insert and edit comments in c - c

Now I have a bunch of C source files with already inserted comments, which are in format /*****......*****/ for functions and /*....*/ for phrases and variables. My task is to document these files with doxygen. The problem is obvious: the comment formats are not supported by doxygen. So I have to find a way to modify the comment format of the files and also add other further comments.
I've tried with gvim with doxygen toolkit. I was only able to insert something simple like
/**
* #brief
*/
only to functions. So I'm wondering if there's a way for me to modify the already existing comments. Thank you in advance.

For Vim:
\/\*\*\*\*\*\_.\{-}\*\*\*\*\*\/
Finds
/*****
abcdef
*****/
void main()
{
int a = 0;
/**** abcdef ****/
}
/***** abcdef *****/
void function()
{
}
/*****
abcdef
abcdef
abcdef
*****/
void function2()
{
}
Which can easily be convert to a sub expression replacement VIM command:
:1,$ s/\(\/\*\*\*\*\*\)\(\_.\{-}\)\(\*\*\*\*\*\/\)/\/\*\*\2\*\//g
:)
Perhaps python/grep-awk would be a better choice here!
EDIT: Comment - Above solution is strictly based on the /***** pattern (i.e. number of '*' in /*****)

Related

Doxygen are not collecting all \todo in global todo list

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.

Why do I find `/*{{{*/` and `/*}}}*/` around functions in C code? [duplicate]

I just downloaded complete source code of PHP from php.net (PHP 5.4.0 [tar.bz2]).
They are often using three curly brackets together as given below (The following code snippet extracted form ext/ctype/ctype.c.)
/* {{{ proto bool ctype_digit(mixed c)
Checks for numeric character(s) */
static PHP_FUNCTION(ctype_digit)
{
CTYPE(isdigit);
}
/* }}} */
Does anyone have the idea why they are using these three curly brackets together?
They are vim fold markers, they make it easy to collapse and expand the text inbetween the triple curly braces in vim, in the example shown alternating between:
...
/* {{{ proto bool ctype_digit(mixed c)
Checks for numeric character(s) */
static PHP_FUNCTION(ctype_digit)
{
CTYPE(isdigit);
}
/* }}} */
...
and just
...
/* {{{ proto bool ctype_digit(mixed c)
...
If you look at the end of the file where you find them, you'll often find a block like this:
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
Which is another more-obvious indicator that these comments relate to vim.

Add debug print code in every function using vim

I have a huge code file and want to insert print code in every function.
I know debugging is one option but I am new to Kernel and kgdb is not an easy and immediate option hence I want to use printf temporarily.
I used vim's multiple buffers to do this task faster, but want to know if there is any way to automate it in .vimrc
Here is what the final code must look like
void foo(int a, int b) {
printf("Some print");
// ...
}
int bar() {
printf("Some print");
// ...
}
void bleh(int b) {
printf("Some print");
// ...
}
one quick way to do it is in the shell:
find -name '*.c' | xargs vim
In vim, you start recording with qq a macro, make use of the global command
:g/\v\s*(void|int) \w+\([^)]*\)/normal A^Mprint("some print");
And then you use the wonderful argdo command:
:argdo normal #q
To save the changes you use:
:argdo normal :w^M
That will add print("someprint") to every function on the located c source code files. If you want to use the function name or the file name in the print statement, you can use the global command with a little complex substitution like (not tested):
:global /\v\s*(void|int) \w+([^)]*)/s/\v(\w+)\([^]]*\)\s* {/\=submatch(0) . '\r\t\tprint(in file.function:'. expand('%') .'.'. submatch(1) . ');'
Remember that ^M and ^[ are not literal strings, they are inserted with <C-v><CR> and <C-v><Esc>
Hope this help

Search and replace a string as shown below

I am reading a file say x.c and I have to find for the string "shared". Once the string like that has been found, the following has to be done.
Example:
shared(x,n)
Output has to be
*var = &x;
*var1 = &n;
Pointers can be of any name. Output has to be written to a different file. How to do this?
I'm developing a source to source compiler for concurrent platforms using lex and yacc. This can be a routine written in C or if u can using lex and yacc. Can anyone please help?
Thanks.
If, as you state, the arguments can only be variables and not any kind of other expressions, then there are a couple of simple solutions.
One is to use regular expressions, and do a simple search/replace on the whole file using a pretty simple regular expression.
Another is to simply load the entire source file into memory, search using strstr for "shared(", and use e.g. strtok to get the arguments. Copy everything else verbatim to the destination.
Take advantage of the C preprocessor.
Put this at the top of the file
#define shared(x,n) { *var = &(x); *var1 = &(n); }
and run in through cpp. This will include external resources also and replace all macros, but you can simply remove all #something lines from the code, convert using injected preprocessor rules and then re-add them.
By the way, why not a simple macro set in a header file for the developer to include?
A doubt: where do var and var1 come from?
EDIT: corrected as shown by johnchen902
When it comes to preprocessor, I'll do this:
#define shared(x,n) (*var=&(x),*var1=&(n))
Why I think it's better than esseks's answer?
Suppose this situation:
if( someBool )
shared(x,n);
else { /* something else */ }
In esseks's answer it will becomes to:
if( someBool )
{ *var = &x; *var1 = &n; }; // compile error
else { /* something else */ }
And in my answer it will becomes to:
if( someBool )
(*var=&(x),*var1=&(n)); // good!
else { /* something else */ }

Replacing C++ single-line comments with C89 comments

What's a good way to replace single-line // input number comments with multi-line /* input number */ comments?
I don't have any preference for the language used to accomplish the task; I was thinking of Perl or sed. The source language will be C (ANSI X3.159-1989).
Simple scripts like
while(<>) {
if (m#^(.*?)//#) {
print $1;
} else {
print $_;
}
}
would be fooled by strings containing // and are not OK. Similarly, // inside a multi-line comment should be left alone.
Edit: Code can assume that there are no trigraphs.
This is the opposite of replace C style comments by C++ style comments. It is similar to Replacing // comments with /* comments */ in PHP (though the accepted answer there cannot handle the special cases I mentioned and so is arguably wrong).
You can use boost::wave lexer's output to replace all the c++ style comments to C style comments. without getting bothered about the edge cases.
#include <iostream>
#include <fstream>
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
typedef boost::wave::cpplexer::lex_token<> token_type;
typedef boost::wave::cpplexer::lex_iterator<token_type> token_iterator;
typedef token_type::position_type position_type;
int main()
{
const char* infile = "infile.h";
const char* outfile = "outfile.h";
std::string instr;
std::stringstream outstrm;
std::string cmt_str;
std::ifstream instream(infile);
std::ofstream outstream(outfile);
if(!instream.is_open()) {
std::cerr << "Could not open file: "<< infile<<"\n";
}
if(!outstream.is_open()) {
std::cerr << "Could not open file: "<< outfile<<"\n";
}
instream.unsetf(std::ios::skipws);
instr = std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
std::istreambuf_iterator<char>());
position_type pos(infile);
token_iterator it = token_iterator(instr.begin(), instr.end(), pos,
boost::wave::language_support(boost::wave::support_cpp|boost::wave::support_option_long_long));
token_iterator end = token_iterator();
boost::wave::token_id id = *it;
while(it!=end) {
//here you check the c++ style comments
if(id == boost::wave:: T_CPPCOMMENT) {
std::cout<<"Found CPP COMMENT";
cmt_str = it->get_value();
cmt_str[0] = '/';
cmt_str[1] = '*';
//since the last token is the new_line token so replace the new line
cmt_str[cmt_str.size()-1] = '*';
cmt_str.push_back('/');
//and then append the newline at the end of the string
cmt_str.push_back('\n');
outstrm<<cmt_str;
}
else {
outstrm<<it->get_value();
}
++it;
id = *it;
}
outstream<<outstrm;
return 0;
}
For further documentation please see:
http://www.boost.org/doc/libs/1_47_0/libs/wave/index.html
There are a lot of corner cases to consider. Stray //s can appear in string literals, character constants (yes, really), and within /* ... */ comments and // comments. Line-splicing with trailing \ characters can really mess things up -- and a \ can be represented as the trigraph ??/. I seriously doubt that I've thought of all of them.
If you need a 100% reliable replacement, you're going to have to reproduce (or steal!) part of the preprocessor of a C compiler.
If you don't need 100% reliability, you might consider just doing a naive replacement, then comparing the input to the output and manually cleaning up any problems. (For typically code, it's likely that there won't be any, but you'll need to check.) The practicality of this approach depends in part on how much code you need to translate.
Most of the corner cases will result in code that won't compile:
printf("Hello // world\n");
-->
print("Hello /* world\n"); */
You might also consider whether this is really necessary. Most C89/C90 compilers do support // comments, at least optionally.
This won't cover 100% of corner cases, but it covers the ones you mentioned in your request.
#!/usr/bin/env python
import re
from sys import stdin, stdout
for line in stdin.readlines():
line = line[:-1] # Trim the newline
stripped = re.sub(r'[\'"].*[\'"]', '', line) # Ignore strings
stripped = re.sub(r'/\*.*\*/', '', stripped) # Ignore multi-line comments
m = re.match(r'.*?//(.*)', stripped) # Only match actual C++-style comments
if m:
offset = len(m.group(1)) + 2
content = line[:offset*-1] # Get the original line sans comment
print '%s/* %s */' % (content, m.group(1)) # Combine the two with C-style comments
else:
print line

Resources