nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.38k stars 324 forks source link

How to find function, macro, and type definitions #691

Open alejandro-colomar opened 2 years ago

alejandro-colomar commented 2 years ago

I developed the following bash(1) functions to help me find function definitions and type definitions. They make use of some rare programs such as pcregrep(1) and some GNU extensions to POSIX programs (such as grep -h), but I hope they are useful to most users/programers.

function grep_ngx_macro()
{
    if (($# != 1)); then
        >&2 echo "Usage: ${FUNCNAME[0]} <macro>";
        return 1;
    fi;

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "define $1\b" \
    | sort \
    | xargs pcregrep -Mn "(?s)define $1\b.*?[^\\\\]$" /dev/null \
    | sed -E 's/^[^: ]+:[0-9]+:/\n\n&\n\n/';
}

function grep_ngx_func()
{
    if (($# != 1)); then
        >&2 echo "Usage: ${FUNCNAME[0]} <func>";
        return 1;
    fi;

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "\b$1\b" \
    | sort \
    | xargs pcregrep -Mn "(?s)^\w[\w\s*]+\s\**$1\([^;{]*?;" /dev/null \
    | sed -E 's/^[^: ]+:[0-9]+:/\n\n&\n\n/';

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "^$1\b" \
    | sort \
    | xargs pcregrep -Mn "(?s)^\$[\w\s*]+?^$1\(.*?^}" /dev/null \
    | sed -E 's/^[^: ]+:[0-9]+:/\n\n&/';
}

function grep_ngx_type()
{
    if (($# != 1)); then
        >&2 echo "Usage: ${FUNCNAME[0]} <type>";
        return 1;
    fi;

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "^} $1;" \
    | sort \
    | while read f; do
        grep -n "^} $1;" $f /dev/null \
        | sed -E 's/^([^: ]+:[0-9]+:).*/\n\n\1\n/';

        tac <$f \
        | sed -n "/^} $1;/,/^typedef/p" \
        | tac;
    done;

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "^typedef .* $1;" \
    | sort \
    | xargs grep -n "^typedef .* $1;" /dev/null \
    | sed -E 's/^[^: ]+:[0-9]+:/\n\n&\n\n/';

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -h "^typedef .* *$1;" \
    | sed -e 's/^typedef //' -e "s/ *$1;.*//" \
    | while read t; do
        grep_ngx_type "$t";
    done;

    find src -type f \
    | grep '\.[ch]$' \
    | xargs grep -l "$1 *{" \
    | sort \
    | xargs pcregrep -Mn "(?s)^\$[\w\s]+?$1 {.*?^}.*?;" /dev/null \
    | sed -E 's/^[^: ]+:[0-9]+:/\n\n&/';
}

function grep_ngx()
{
    if (($# != 1)); then
        >&2 echo "Usage: ${FUNCNAME[0]} <identifier>";
        return 1;
    fi;

    grep_ngx_type "$1";
    grep_ngx_func "$1";
    grep_ngx_macro "$1";
}

We might want to consider adding this to the repository, maybe to a scripts/ directory. For the moment I'll leave it here so it's useful for all.

alejandro-colomar commented 2 years ago

Examples of usage:

$ grep_ngx;
Usage: grep_ngx <identifier>
$ grep_ngx nxt_http_return_ctx_t;

src/nxt_http_return.c:22:

typedef struct {
    nxt_http_action_t  *action;
    nxt_str_t          location;
    nxt_str_t          encoded;
} nxt_http_return_ctx_t;
$ grep_ngx nxt_http_route_rule_t;

src/nxt_http.h:202:

typedef struct nxt_http_route_rule_s       nxt_http_route_rule_t;

src/nxt_http_route.c:105:

struct nxt_http_route_rule_s {
    /* The object must be the first field. */
    nxt_http_route_object_t        object:8;
    uint32_t                       items;

    union {
        uintptr_t                  offset;

        struct {
            u_char                 *start;
            uint16_t               hash;
            uint16_t               length;
        } name;
    } u;

    nxt_http_route_pattern_t       pattern[0];
};
$ grep_ngx nxt_http_route_rule_s;

src/nxt_http_route.c:105:

struct nxt_http_route_rule_s {
    /* The object must be the first field. */
    nxt_http_route_object_t        object:8;
    uint32_t                       items;

    union {
        uintptr_t                  offset;

        struct {
            u_char                 *start;
            uint16_t               hash;
            uint16_t               length;
        } name;
    } u;

    nxt_http_route_pattern_t       pattern[0];
};
$ grep_ngx nxt_uid_t;

src/nxt_credential.h:10:

typedef uid_t   nxt_uid_t;
$ grep_ngx nxt_sprintf;

src/nxt_sprintf.h:15:

NXT_EXPORT u_char *nxt_cdecl nxt_sprintf(u_char *buf, u_char *end,
    const char *fmt, ...);

src/nxt_sprintf.c:56:

u_char * nxt_cdecl
nxt_sprintf(u_char *buf, u_char *end, const char *fmt, ...)
{
    u_char   *p;
    va_list  args;

    va_start(args, fmt);
    p = nxt_vsprintf(buf, end, fmt, args);
    va_end(args);

    return p;
$ grep_ngx nxt_http_field_set;

src/nxt_http.h:98:

#define nxt_http_field_set(_field, _name, _value)                             \
    do {                                                                      \
        (_field)->name_length = nxt_length(_name);                            \
        (_field)->value_length = nxt_length(_value);                          \
        (_field)->name = (u_char *) _name;                                    \
        (_field)->value = (u_char *) _value;                                  \
    } while (0)
$ grep_ngx nxt_inline;

src/nxt_clang.h:11:

#define nxt_inline     static inline __attribute__((always_inline))
$ grep_ngx NXT_MAYBE_UNUSED

src/nxt_clang.h:137:

#define NXT_MAYBE_UNUSED         __attribute__((__unused__))

src/nxt_clang.h:141:

#define NXT_MAYBE_UNUSED
tippexs commented 2 years ago

Good stuff! We should add some preflight checks for the tools needed. Can do this. Is there a way to contribute or should I just copy the script in my repo and hack around?

alejandro-colomar commented 2 years ago

Good stuff! We should add some preflight checks for the tools needed. Can do this. Is there a way to contribute or should I just copy the script in my repo and hack around?

Hmmm, now you say it, this tool would be useful not only for us, but for any C programmer out there. I'm going to create a new repository, called maybe cutils, and put this as a #!/bin/bash script there called grepc. The tool could be improved to detect other styles in the future too.

I'll update here when I have it ready in a repo.

alejandro-colomar commented 2 years ago

Main git repository: http://www.alejandro-colomar.es/src/alx/alx/grepc.git/

GitHub mirror: https://github.com/alejandro-colomar/grepc.git

alejandro-colomar commented 2 years ago

@tippexs you (and anyone) can contribute to that repo, via email (patches) or also github PRs and issues.

Regarding deps, I created these two issues: https://github.com/alejandro-colomar/grepc/issues/3 https://github.com/alejandro-colomar/grepc/issues/2