3

I'm doing a GCC Plugin to check a coding style for C and header files. I check the coding style at the compilation with :

register_callback(plugin_info->base_name, PLUGIN_START_UNIT, start_unit_callback, NULL);
register_callback(plugin_info->base_name, PLUGIN_INCLUDE_FILE, include_file_callback, NULL);

The first line is only to check C files and the second one is to check headers files (.h).

But then I have performance issue when it come to the header check. In fact, it checks the system headers too ! And I would like it does not do that. This is the list of headers file that GCC gets :

/usr/include/stdio.h
/usr/include/bits/libc-header-start.h
/usr/include/features.h
/usr/include/features-time64.h
/usr/include/bits/wordsize.h
/usr/include/bits/timesize.h
/usr/include/bits/wordsize.h
/usr/include/sys/cdefs.h
/usr/include/bits/wordsize.h
/usr/include/bits/long-double.h
/usr/include/gnu/stubs.h
/usr/include/gnu/stubs-64.h
/usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/include/stddef.h
/usr/lib/gcc/x86_64-pc-linux-gnu/13.1.1/include/stdarg.h
/usr/include/bits/types.h
/usr/include/bits/wordsize.h
/usr/include/bits/timesize.h
/usr/include/bits/wordsize.h
/usr/include/bits/typesizes.h
/usr/include/bits/time64.h
/usr/include/bits/types/__fpos_t.h
/usr/include/bits/types/__mbstate_t.h
/usr/include/bits/types/__fpos64_t.h
/usr/include/bits/types/__FILE.h
/usr/include/bits/types/FILE.h
/usr/include/bits/types/struct_FILE.h
/usr/include/bits/stdio_lim.h
/usr/include/bits/floatn.h
/usr/include/bits/floatn-common.h
/usr/include/bits/long-double.h
test.h

The only include that I've made myself is the test.h, so it must not check the others files.

So do you know a way to extract all the system files included ?

I've tried to just skip all the includes from /usr/ and /lib/ but that is not a good practice.

I've tried to see if I could make the callback at another moment of the compilation, but it did not make well (It does not check for headers).

Thank you for reading me ! Hoping you could help me :)

neo-jgrec
  • 167
  • 8
  • "I've tried to just skip all the includes from `/usr/` and `/lib/` but that is not a good practice." Why do you think that's not a good practice? It seems reasonable to me to conclude that any header file located under the system directories `/usr/` and `/lib/` are system headers. – Andrew Henle Jun 10 '23 at 15:00
  • @AndrewHenle what about /usr/home/user/someproject/include under /usr directory? – yvs2014 Jun 10 '23 at 16:20
  • @yvs2014 `/usr/home/...`?!?!?! Some admin is a bit clueless about where home directories for users go. They don't belong under `/usr` for a lot of reasons, least of which `/usr` can be mounted read-only. – Andrew Henle Jun 10 '23 at 16:30
  • @AndrewHenle "/usr/home/...?!?!?! Some admin is a bit clueless about where home directories for"
    on freebsd for example there are users' homes located in '/usr/home' and '/home' is symlink to '/usr/home' (at least at last time I've installed it)
    – yvs2014 Jun 10 '23 at 16:44
  • @AndrewHenle there's a bit about those who decided so and where it came from https://en.m.wikipedia.org/wiki/Home_directory – yvs2014 Jun 10 '23 at 17:08
  • @yvs2014 I'm on linux, so thoses paths are not correct in my case ! It's `/home/${usr}`. And the defaults includes are on `/usr/include` – neo-jgrec Jun 10 '23 at 17:22
  • @AndrewHenle .For instance I think about someone I know being on NixOS. And his headers are in a /nix/store (if I remember correct). – neo-jgrec Jun 10 '23 at 17:23
  • @neo-jgrec as an option it's possible to run something like `cpp -v search starts here:` and `End of search list.`
    Suppose there should be a bit more direct way to get system include directories with some gcc specific function, but sorry I've not gone deep into c preproprecossor details.
    – yvs2014 Jun 10 '23 at 17:41
  • Sooo @yvs2014, you're suggesting to do something like a `popen` for the command you gave me in the code to check which files must be checked and thoses who should'nt ? – neo-jgrec Jun 10 '23 at 17:48
  • 1
    @neo-jgrec it's just as a last resort option (at least you can get the precise list of system inc dirs), I suggest to wait a while, maybe someone gives a hint how to get that path-list properly – yvs2014 Jun 10 '23 at 17:54
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254026/discussion-between-neo-jgrec-and-yvs2014). – neo-jgrec Jun 10 '23 at 18:14

1 Answers1

1

So as a temporary option. Waiting for someone to have a better method, I've made this function :

char **get_system_includes(void)
{
    FILE *fp;
    char line[MAX_LINE_LENGTH];
    char **includes = (char**)xmalloc(sizeof(char *) * 1024);
    int includes_count = 0;

    fp = popen("echo | gcc -E -v - 2>&1 | awk '/#include </,/^End of search/'", "r");
    if (fp == NULL) {
        error("Could not get system includes");
        exit(1);
    }

    while (fgets(line, sizeof(line), fp) != NULL) {
        line[strcspn(line, "\n")] = 0;

        if (strstr(line, "#include <") != NULL
            || strstr(line, "End of search") != NULL)
            continue;

        char *start = line;
        for (; *start == ' ' || *start == '\t'; start++);

        includes[includes_count] = (char*)xmalloc(strlen(start) + 1);
        strcpy(includes[includes_count], start);
        includes_count++;
    }

    pclose(fp);
    includes[includes_count] = NULL;
    return includes;
}

Thanks to it, I can retrieve a vector of strings containing all the system includes dir I want to ignore.

neo-jgrec
  • 167
  • 8