emacs count c functions in a .c/.h src file - c

Does emacs have a function to count the no. of functions in .c/.h C src file?
I would like to be able to count a (large) no. of functions in a .c file and compare this to the no. of functions in the associated unit-test .c file to establish whether every function has a unit-test
ideally there is something built-in to do this as opposed to requiring some sort of reg-exp?

You can use semantic's tag generation to achieve this.
Semantic is a very powerful and underused feature of Emacs. Semantic can parse your .c and .h files and generate tags that you can look through to find your answer. I have written up examples for you:
First, ensure you have the semantic library loaded.
(defun c--count-things-in-buffer (thing buffer)
"return the count of THINGs in BUFFER.
THING may be: 'function, 'variable, or 'type"
(with-current-buffer buffer
;; get the buffers tags, they will be generated if not already
;; then remove the ones that are not 'function tags
;; return the count of what is left
(length (remove-if-not (lambda (tag) (equal thing (second tag)))
(semantic-fetch-tags)))))
(defun c-count-functions-in-buffer (buffer)
"Count and message the number of function declarations in BUFFER"
(interactive "b")
(message "%s has %d functions"
buffer
(c--count-things-in-buffer 'function buffer)))
(defun c-count-variables-in-buffer (buffer)
"Count and message the number of variable declarations in BUFFER"
(interactive "b")
(message "%s has %d variables"
buffer
(c--count-things-in-buffer 'variable buffer)))
(defun c-count-types-in-buffer (buffer)
"Count and message the number of type declarations in BUFFER"
(interactive "b")
(message "%s has %d types"
buffer
(c--count-things-in-buffer 'type buffer)))
Try evaluating this in your scratch buffer then switch to your .c file and do M-x c-count-functions-in-buffer
The information brought back from semantic-fetch-tags has everything you need to solve your unit test problems.
Let's say you have a function called Foobar and your unit test are written like: Test_Foobar. You could get the tags for the .c file and the tags for the test file and do a check for every function in the c file there exists a tag in the test file that matches Test_. This would likely be better than simply counting the total number of functions.
Run this code in your scratch buffer with C-j:
(with-current-buffer "what-ever-your-c-buffer-is.c" (semantic-fetch-tags))
Here you'll be able to see all the great info that comes back that you can use for this.

Related

How to find all C functions starting with a prefix in a library

For a small test framework, I want to do automatic test discovery. Right now, my plan is that all tests just have a prefix, which could basically be implemented like this
#define TEST(name) void TEST_##name(void)
And be used like this (in different c files)
TEST(one_eq_one) { assert(1 == 1); }
The ugly part is that you would need to list all test-names again in the main function.
Instead of doing that, I want to collect all tests in a library (say lib-my-unit-tests.so) and generate the main function automatically, and then just link the generated main function against the library. All of this internal action can be hidden nicely with cmake.
So, I need a script that does:
1. Write "int main(void) {"
2. For all functions $f starting with 'TEST_' in lib-my-unit-tests.so do
a) write "extern void $f(void);"
b) write "$f();
3. Write "}"
Most parts of that script are easy, but I am unsure how to reliably get a list of all functions starting with the prefix.
On POSIX systems, I can try to parse the output of nm. But here, I am not sure if the names will always be the same (on my MacBook, all names start with an additional '_'). To me, it looks like it might be OS/architecture-dependent which names will be generated for the binary. For windows, I do not yet have an idea on how to do that.
So, my questions are:
Is there a better way to implement test-discovery in C? (maybe something like dlsym)
How do I reliably get a list of all function-names starting with a certain prefix on a MacOS/Linux/Windows
A partial solution for the problem is parsing nm with a regex:
for line in $(nm $1) ; do
# Finds all functions starting with "TEST_" or "_TEST_"
if [[ $line =~ ^_?(TEST_.*)$ ]] ; then
echo "${BASH_REMATCH[1]}"
fi
done
And then a second script consumes this output to generate a c file that calls these functions. Then, cmake calls the second script to create the test executable
add_executable(test-executable generated_source.c)
target_link_libraries(test-executable PRIVATE library_with_test_functions)
add_custom_command(
OUTPUT generated_source.c
COMMAND second_script.sh library_with_test_functions.so > generated_source.c
DEPENDS second_script.sh library_with_test_functions)
I think this works on POSIX systems, but I don't know how to solve it for Windows
You can write a shell script using the nm or objdump utilities to list the symbols, pipe through awk to select the appropriate name and output the desired source lines.

Read a line of c code from file and execute in a c program

I have a C program which calculates f(x) for some x values (main.c). I need to get a line of c code from file and that code is my function to execute (function.dot). For example function.dot will contain:
pow((1-x), 0.333);
I need to read this file, get that function and execute in my code (main.c). How can I do that?
Basic steps would be:
Read the line from the file.
Generate a new source file which wraps the line of code inside appropriate code.
Invoke a compiler to compile that code into a shared object/dll.
Load the library.
Call the function in the library.
If the single line of code in the file could be any language, it would be far easier to use something like Lua that can be linked into your main executable.
I will provide some options:
Switch to another interpreted language including python, ruby, perl, ...
If you are working on small project, I recommend this option.
Implement your own interpreter in C.
Parse your input, analyze it, execute it. You might find open source implementations: one choice is slang
http://www.jedsoft.org/slang/doc/html/slang.html
Call C compiler and dynamically link it.
It depends on your operating system but system or exec functions help you to call your compiler to handle your input file. If you are using Linux, dlsym can open a shared-object compiled from your input file.
You might need to convert your input file into C program.
Very slow to compile but fastest to run.
You have several options I can think of:
1) Switch to any number of interpreted langauges (python, perl, etc.) which support this as an easy mechanism. (Example: in python
data = open("function.dot").read()
x = 5
eval(data) #note that this is unsafe if you can't trust data, and you might also need to play with environment
)
2) You could wrap the code in it's own c file... something like (but with more error checking etc... you probably don't want to do this)
void generate_c_program(char *line)
{
FILE *fp = fopen("myfile.c","wt");
fprintf(fp,"#include <math.h>\nint main(char *argv, int argc) {\n double x = atof(argv[1]); printf(\"%f\",(%s));}\n");",line); //this is also unsafe if you can't trust data
fclose(fp);
//now execute gcc myfile.c
//now execute a.out
//optionally cleanup by deleting a.out and myfile.c
}
3) Effectively write your own compiler / parser (which may be fairly easy IF you've done this before and the number of functions / operations you need to support is small or may be a much bigger deal and will rather not fit in this answer)... the extensible way would be to use LEX/YACC or similar)

Visiting required file from .emacs

Is it possible to visit a mentioned file in require like:
(require 'key-chord)
For which when clicking on "key-chord" (or some other input than clicking), makes you visit that file?
EDIT: Given that we want to visit the file "key-chord.el"
Put the cursor on whatever is being required, e.g. the "k" in "key-chord", and do M-x ffap RET RET. ffap is an alias for find-file-at-point, which understands require, at least in lisp-mode. I have ffap bound to C-x f, because I rarely have use for that key's default binding.
Some Emacs installations don't have the .el files (only the .elc files). In Debian/Ubuntu, you need to install a separate package to get them (emacs-version-el, IIRC).
locate-library tells you the file name, and find-file opens the file in a buffer for editing. (You might want find-file-read-only if you merely want to inspect it.)
(find-file (locate-library "key-chord.el" t))
You can turn it into a function, something like this:
(defun find-locate-library (lib)
"Visit the source for library LIB in a buffer."
(let ((location (locate-library (concat lib ".el") t)))
(if location
(find-file location)
(message "Could not find library %s" lib)) ))
How to hook this into a viewing or editing buffer is a separate topic. I suppose you could amend Elisp mode to make library names clickable, but I cannot tell off-hand how to do that.
Thanks to #Deokhwan Kim for the suggestion to limit search to ".el" files only.
M-x find-library RET prompts you for the name of a library, and then visits that file.
Calling it with point on a valid library name will make that the default prompt value.
Calling it with point anywhere within a require statement will also do the right thing.
I use find-library frequently, and bind it to C-hC-l for convenience.

fputs( _("") ) what does the underscore stand for?

I finally got myself to look at some Linux code. I am looking right now at ls.c.
At the function usage() at the bottom I found a lot of these statements:
fputs (_("\
List information about the FILEs (the current directory by default).\n\
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
\n\
"), stdout);
What does _("") mean? Is it something like L"string" or _T"string" or something completely new? I must also admit I don't know what words to use to search for something like this.
It's a convention used by libintl a.k.a. gettext, for translatable strings. When it runs, gettext function (which _ is aliased to) will return either original or translated string, depending on locale settings and availability of said string.
_ is a macro often used with the GNU gettext package.
GNU gettext is a package that:
takes lists of message strings intended for humans to read, and translations of those strings into other languages, and compiles them into databases;
provides a routine, named gettext(), to look up message strings in that database and return the translation for the message into a particular language.
If a program wanted to print a message in the language selected by the user in an environment variable and picked up by a setlocale() call, it would normally do something such as
fprintf(stderr, gettext("I cannot open the file named %s\n"), filename);
gettext() would look up the appropriate translation of the string "I cannot find the file named %s\n" in the database and return the translated string.
However, that's a bit awkward; as the documentation for GNU gettext notes, many programs use a macro to make just _(string) be an alias for gettext(string).
Function names can, of course, contain an _, and an _ can begin a function name. So, it's possible to name a function simply _.
All that's happening is that a #define or a real function is called _.

SHA-1, RFC3174 and RFC4634

New to the community, but not new to programming.
I've been trying to get a collection of hash functions up/running and I succeeded. However I found some weird results and haven't been able to put my finger on it yet. RFC4634 contains a C implementation for SHA-1 and SHA-2 family, which also can accept a file being passed on for hashing. RFC3174 contains a C implementation, but doesn't process file streams. I've been using the C implementation from RFC4634 to verify files, yet the verification process is returning non similar results when I compare them against SHA-1 provided hashes.
Any idea what the reasons could be?
Did you check if you opened the files in ASCII or binary mode? Line end translation may be performed before the hash is being calculated.
Update:
I just compiled the RFC4634 shatestand tried on a sample text file. As long as there isn't a line break, all tools agree. Once you insert a line break, results depend: if the text file uses CR and LF (DOS mode), then shatest produces a different result. If the line end is only LF (UNIX), it still agrees with the other tools.
Update 2:
In the file shatest.c of RFC4634, in function hashfile(...), set fopen to binary mode:
FILE *hashfp = (strcmp(hashfilename, "-") == 0) ? stdin :
fopen(hashfilename, "rb");
/* ^ HERE */

Resources