List all functions declared in header but missing in the source file? - c

Question
Are there some linters/statical analyzers that warn/error on functions, that are declared in the header file but not implemented in the corresponding source file?
Lets say we have the following header (guard omitted):
/* example.h */
int doSomething(int i);
double doSomethingElse(double d);
And the following source:
/* example.c */
#require "example.h"
int doSomething(int i) {
return i + 1;
}
So is there some tool, that can tell me that doSomethingElse() is missing in example.c?
Why asking?
In an exercise we got some headerfiles with a fully fletched interface, and partially prepared sourcefiles, with some functions beeing fully provided, some functions beeing partially provided, and some missing.
For actually running and compiling this programm it was enough to complete the partially provided functions, but still there is some discrepancy between the defined interface in the header and the now provided functions in the source file.
I could go through all header/source pairs by hand and implement the missing funtions, but it would be nice to have some autogenerated todolist.

I'd just do it with grep etc.:
grep ');' foo.h | tr -d ';' | while read decl
do
if ! grep -q "$decl" foo.c
then
echo "not found: $decl"
fi
done
No, this isn't perfect, but it might work if your use case is as simple as you've outlined.

Related

Why linking .cc file works in make file but linking .c file doesn't?

I'm working on a quite large Makefile from the tensorflow repo and I need to add a file link.
After quite some debugging of a link error, I found out that if my file ends with .cc, then the link error disappears, whereas when linking a .c file, the error appears (file content remains the same).
I am linking the file in a Makefile.inc file:
.
.
.
FL_SRCS := \
tensorflow/lite/vis_mi/main.cc \
myFunctions.c \ -->>>>IF I CHANGE THE FILENAME TO myFunctions.cc and link to this .cc file here, it works!!
.
.
.
# Builds a standalone binary.
$(eval $(call vis_test,vis_mi,\
$(FL_SRCS),$(FL_HDRS)))
The link error when using the .c ending ends with:
tensorflow/lite/vis_mi/main.o: In function `main':
tensorflow/lite/vis_mi/main.cc:183: undefined reference to `printMsg()'
../downloads/gcc_embedded/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: link errors found, deleting executable `tensorflow/lite/vis_mi'
collect2: error: ld returned 1 exit status
gmake: *** [tensorflow/lite/vis_mi/Makefile.inc:578: tensorflow/lite/vis_mi/bin/micro_speech] Error 1
The .c file code:
#include <stdio.h>
#include "myFunctions.h"
void printMsg(){
//do something here
}
And the header file:
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H
void printMsg();
#endif /* MYFUNCTIONS_H */
How can I include a file ending with .c? Makefiles are fairly new to me, and didn't want to include all the details, and if you need any further details from the Makefile to answer this question I'm happy to edit my post.
The name resolution for C and C++ functions is different. This is sometimes causing problem to "C" code that is also valid "C++". For example:
int foo(int x) { return x+1 } ;
The code Will create a function called 'foo' when compiled as "C", and will create a function called '_Z3fooi' when compiled as C++. Decoding the C++ name will (using c++filt) will show foo(int). The reason for the difference is that C++ support polymorphic functions (and methods), so that function names also identify the type of their parameters.
The proper solution is to decide on the language of the code. C++ and C are different language, and while it's possible to write code that will be valid for both, it will limit the ability to leverage each function abilities.
Important constraint: If a project contain both C and C++ code, it is important to remember that only functions that follow the "C" conventions can be called between the languages. This is usually implemented with extern "C" directive, and with #ifdef __cplusplus:
See more: https://www.thegeekstuff.com/2013/01/mix-c-and-cpp/ How to call C++ function from C? Call a C function from C++ code

Use preprocessor to "remove" prefix from function in C

I write a framework with lot of function that are named like that :
ICE_ModuleType_FunctionUse()
and everything else have ICE_ prefix (typename, define etc...)
And with preprocessor I would like to remove ICE_ to reduce function name lenght when the user know there is no conflict with other libs.
But the only working way I found was to write every function, type etc... by hand like that :
#define ModuleType_FunctionUse ICE_ModuleType_FunctionUse
Any Idea on how to easly do that ?
You could automatically create a new header file with a name like use_namespace_ICE.h for your clients to use. This file would have the required list of #defines, and can be generated using the utilities nm or dumpbin applied to your library.
For example, if foo.c is:
void ICE_ModuleType_FunctionUse(void) { /* code */ }
then:
cc -c -o foo.o foo.c
nm foo.o | grep ' T _ICE_' | sed 's/.* T _ICE_\(.*\)/#define \1 ICE_\1/'
yields:
#define ModuleType_FunctionUse ICE_ModuleType_FunctionUse
As the comments tell you, there is no way, or no easy way, to shorten identifiers once written in your source code. However, you can reduce the typing for things that still need to be written:
#define ModuleType_FunctionUse ICE_ModuleType_FunctionUse
This defines that the short name will be replaced with the longer name.

unused functions detection utility for c

I am trying to measure my code coverage utilization on a C project consist of several libraries, and main program.
Is there a utility that can help me find which function I dont use from both libraries and main program.
I want to build list of functions (public functions) that are not used by my main program, in order to ignore them in my code coverage report.
If you are using gcc you compile your code with option:
-Wunused-function
Warn whenever a static function is declared but not defined or a non-inline static function is unused. This warning is enabled by -Wall.
cflow can create a call graph for the program, but it doesn't work well with pointers to functions in some cases.
for eaxample:
#include <stdio.h>
static int f1(){
return 1;
}
int (*p_f1)() = f1;
int main() {
p_f1();
return 0;
}
There are coverage tools available for free - for example "gcov" that runs on go with the gcc tool suite. However, Code Coverage only tells you which functions get hit by your testing (or whatever you do to excercise the code), so for example
ptr = malloc(...);
if (!ptr)
{
allocation_failed(__FILE__, __LINE__);
}
would only show that allocation_failed is called if you are also using some tool that makes your allocations fail from time to time.
I'm not aware of a tool that will show you what functions are not used across larger systems (with multiple libraries, etc). I expect you could make something by using the output of "nm" and a bit of "pulling things in". It won't cover foo and bar as unusued in this case:
unit1.c:
extern int foo(void);
int bar()
{
return foo();
}
unit2.c:
int foo(void)
{
return 42;
}
int baz(void)
{
return bar();
}
and then baz isn't used anywhere. But if you remove baz, it will show that bar is not called, and then you can remove foo after that...
Edit: Crazy idea time - how about taking every C file in the project and just concatenating the whole thing into a a single .C file, then add static at the beginning of every function, and compiling with -Wunused-functon - I'm sure there will be some "interesting" effects from this if your code isn't extremely well written, but it may be worth a try [it would be fairly easy to do this in a Linux system, something like find . -name "*.c" -print | xargs cat {} > giantsource.c - you then need a little bit of sed or something to label all functions static, which I'm not quite sure how you'd go about doing - it depends very much on the formatting of your code.
You may want to have a look at this:
http://www.gedanken.demon.co.uk/cxref/
I haven't used it, but any decent cross referencing tool should be able to identify anything that is "not used" as not having any references. Of course, you'll probably still have to run over the code severa times to weed out the functions that are used by functions that aren't being called, etc.
cflow has an option to build a cross-reference table: --xref
The format of the output is described by GNU cflow: Cross-Reference
GNU cflow is also able to produce cross-reference listings. This mode is enabled by --xref (-x) command line option. Cross-reference output lists each symbol occurrence on a separate line. Each line shows the identifier and the source location where it appears. If this location is where the symbol is defined, it is additionally marked with an asterisk and followed by the definition. For example, here is a fragment of a cross-reference output for d.c program:
printdir * d.c:42 void printdir (int level,char *name)
printdir d.c:74
printdir d.c:102
It shows that the function printdir is defined in line 42 and referenced twice, in lines 74 and 102.
To detect unused functions, search the line with a star not followed by a line with the same prefix. The following GNU Awk code print the unused functions:
{
if( $2 == "*" ) {
if( f ) {
print f
}
f = $1
}
else {
f = ""
}
}
The command may be:
cflow -x src/*.c src-gen/*.c | awk -f find-unused-functions.awk

Pre-preprocessor

I want to have a C pre-preprocessor which is filtering some #define statements from the sourcecode without changing anything else.
Why? This should be used to remove some client specific code from the sources if the source is handed out to another client.
Does anyone know of an existing solution?
Thanks!
Simon
You can use something like awk instead of CPP ? Add some flags in your code surrounding the piece of code to be removed. For example:
(...)
//BEGIN_REMOVE_THIS_CODE
printf("secret code");
//END_REMOVE_THIS_CODE
(...)
then write a awk script to remove this code, something like...
BEGIN { write=1;}
/^\/\/BEGIN_REMOVE_THIS_CODE/ { write=0; next;}
/^\/\/END_REMOVE_THIS_CODE/ { write=1; next;}
{
if(write==1) print $0;
}
I recommend using an additional macro language layer for code filtering, like filepp. You may use a C preprocessor friendly syntax to express which parts belongs to which clients.
//%ifdef CLIENT_A
code for client A
//%endif
//%ifdef CLIENT_B
code for client B
//%endif
//%if "CLIENT_A" || "CLIENT_B"
code for client A and B
//%endif
The '//%' prefix enables You to compile the code unmodified. You may run filepp before You giving out the code to a client.
This sounds like what I asked about in Is there a C pre-processor which eliminates ifdef blocks based on values defined. The best answer I got was sunifdef, or 'Son of unifdef', which has worked reliably for me on some excessively contorted conditional code (the accumulated crud from over 20 years of development on a wide variety of platforms with an inadequate theory of how to do platform-specific compilation).
I don't think you need a preprocessor for this. If you don't have nested #ifdef's in your code, any regex engine can remove anything that is located between #ifdef CLIENT and #endif (use non-greedy matching to match first #endif, not last).
I would put the client specific code in a separate directory or possibly part of a different project that would need to be checked out of the source control.
Put a function call that would be stubbed out or (I forget the proper term) loosely linked so that another function can be put in its place.
If you're using gcc, then you can use:
gcc <insert files here> -E
The -E option tells gcc to only preprocess the sources, and not to compile them.
Or, you could use grep to filter out specific files and let the preprocessor loose on them only.
grep -r '#define CLIENT_CODE' ./*.h
You can also try unifdef which is rather simpler than sunifdef.
Why don't you do something like:
client_a_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.1; };
// ...
client_b_specific_functions_definition.c
double discount_for_paying_upfront() { return 0.05; };
// ...
When you hand out the code it is just a matter of selecting the right file with their specific definitions.
Then you would create a header file to include it where you need to access the client specific code with something like:
client_functions.h
#pragma once
double discount_for_paying_upfront();
#define stringify(x) #x
#define FILE2(a) stringify(client_##a##_specific_functions_definition.c)
#define FILE(a) FILE2(a)
#include FILE(CLIENT_NAME)
#undef stringify
#undef FILE2
#undef FILE
Then say you #include "client_functions.h" in your main.c. You could compile it with:
gcc -DCLIENT_NAME=a main.c -o a.exe
gcc -DCLIENT_NAME=b main.c -o b.exe
as far as I know... the preprocessor can be run as a separate step (using the correct compiler optios) . This way you can do whatever you want with the processed code.

How to store a version number in a static library?

How can I store a version number in a static library (file.a) and later check for its version in Linux?
P.S. I need possibility to check version of file any time without any special executable using only by shell utilities.
In addition to providing a static string as mentioned by Puppe, it is common practice to provide a macro to retrieve the version check for compatibility. For example, you could have the following macros (declared in a header file to be used with your library):
#define MYLIB_MAJOR_VERSION 1
#define MYLIB_MINOR_VERSION 2
#define MYLIB_REVISION 3
#define MYLIB_VERSION "1.2.3"
#define MYLIB_VERSION_CHECK(maj, min) ((maj==MYLIB_MAJOR_VERSION) && (min<=MYLIB_MINOR_VERSION))
Notice with the MYLIB_CHECK_VERSION macro, I'm assuming you want a specific major rev and a minor rev greater than or equal to your desired version. Change as required for your application.
Then use it from a calling application, something like:
if (! MYLIB_VERSION_CHECK(1, 2)) {
fprintf(stderr, "ERROR: incompatible library version\n");
exit(-1);
}
This approach will cause the version information to come from the included header file. Additionally, it will be optimized at compile time for the calling application. With a little more work, you can extract it from the library itself. Read on...
You can also use this information to create a static string stored inside your library, as mentioned by Puppe. Place something like this inside your library:
struct {
const char* string;
const unsigned major;
const unsigned minor;
const unsigned revision;
} mylib_version = {
MYLIB_VERSION, MYLIB_MAJOR_VERSION, MYLIB_MINOR_VERSION, MYLIB_REVISION
};
This will create a struct called mylib_version in your library. You can use this to do further verifications by creating functions inside your library and accessing those from a calling application, etc.
Maybe you could create a string with the version like this:
char* library_version = { "Version: 1.3.6" };
and to be able to check it from the shell just use:
strings library.a | grep Version | cut -d " " -f 2
Creating a new answer based on your edit... Just to avoid confusion :)
If you are looking for a non-code way to solve the problem, you could try this. It's (yet again) an alternative to the strings approach defined by Puppe.
Maybe you could just touch a file called version_1.2.3 and add it to the archive. Then, you could determine the version by looking for the version file using the ar command:
ar t libmylib.a | grep 'version_' | sed -e 's/^version_//'
I'm not sure if that will get you what you need, but there is no standard method for embedding metadata like this in an archive. Maybe you'll find other information you want to store in this "metafile" for the archive.
If you are using gcc, you can use the #ident directive
#ident "Foo Version 1.2.3.4"
void foo(void){ /* foo code here */ }
To get the version just use one of the following:
strings -a foo.o | grep "Foo Version"
strings -a foo.a | grep "Foo Version"
strings -a foo.so | grep "Foo Version"
This will allow you to compile the version into the library with the capability of later stripping it out using strip -R .comment your_file or completely omit it by passing -fno-ident (This will also omit the compiler version comments from the compiled objects)
Several times man 1 ident has been mentioned, so here are details about using that method.
ident is a command that comes with the RCS (Revision Control System), but might also be available if you are using CVS (Concurrent Versions System), or Subversion.
You would use it like this (cloned from the man page):
#include <stdio.h>
static char const rcsid[] =
"$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $";
int main() { return printf("%s\n", rcsid) == EOF; }
and f.c is compiled into f.o, then the command
ident f.c f.o
will output
f.c:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
f.o:
$Id: f.c,v 5.4 1993/11/09 17:40:15 eggert Exp $
If your f.o were added to a static library f.a then ident f.a should show a similar output. If you have several similarly built [a-z].o in your az.a you should find all their strings in the az.a file.
CAVEAT: Just because they are in the .a file doesn't mean they will be included in your program file. Unless the program references them the linker sees no need to include them. So you usually have to have a method in each module to return the string, and the app needs to call that method. There are ways to convince most linkers that it is a required symbol without actually referencing it, but it depends on the linker, and is beyond the scope of this answer.
If instead you are familiar with the SCCS (Source Code Control System) then you would use man 1 what instead, and it would look like this (done with macros to show the flexibility available):
#include <stdio.h>
#define VERSION_STR "5.4"
#define CONFIG "EXP"
#define AUTHOR "eggert"
static char const sccsid[] =
"#(#) " CONFIG " v " VERSION_STR " " __DATE__ " " __TIME__ " " AUTHOR;
int main() { return printf("%s\n", sccsid) == EOF; }
and f.c is compiled into f.o, then the command
what f.c f.o
will output
f.c:
#(#) EXP v 5.4 1993/11/09 17:40:15 eggert
f.o:
#(#) EXP v 5.4 1993/11/09 17:40:15 eggert
PS: both ident and what are commands that come with specific centralized source control systems. If you are using a distributed source control system (like git) the entire concept may not make sense. For some ideas using git see this thread: Moving from CVS to git: $Id:$ equivalent? though the hash isn't the same as a version number. :)

Resources