Em seg., 5 de set. de 2022 às 23:02, David Rowley <dgrowle...@gmail.com>
escreveu:

> On Tue, 6 Sept 2022 at 13:52, Ranier Vilela <ranier...@gmail.com> wrote:
> >
> > Em seg., 5 de set. de 2022 às 22:29, David Rowley <dgrowle...@gmail.com>
> escreveu:
> >> It feels like it would be good if we had a way to detect a few of
> >> these issues much earlier than we are currently.  There's been a long
> >> series of commits fixing up this sort of thing.  If we had a tool to
> >> parse the .c files and look for things like a function call to
> >> appendPQExpBuffer() and appendStringInfo() with only 2 parameters (i.e
> >> no va_arg arguments).
> >
> > StaticAssert could check va_arg no?
>
> I'm not sure exactly what you have in mind. If you think you have a
> way to make that work, it would be good to see a patch with it.
>
About this:

1. StaticAssertSmt can not help.
Although some posts on the web show that it is possible to calculate the
number of arguments,
I didn't get anything useful.
So I left this option.

2. Compiler supports
Best solution.
But currently does not allow the suggestion to use another function.

3.  Owner tool
Temporary solution.
Can help, until the compilers build support for it.

So, I made one very simple tool, can do the basics here.
Not meant to be some universal lint.
It only processes previously coded functions.

pg_check test1.c
line (1): should be appendPQExpBufferStr?
line (2): should be appendPQExpBufferChar?
line (4): should be appendPQExpBufferStr?
line (5): should be appendPQExpBufferStr?

I don't think it's anywhere near the quality to be considered Postgres, but
it could be a start.
If it helps, great, if not, fine.

regards,
Ranier Vilela
/*
 * pg_check.c
 *
 * A simple check syntax program for PostgreSQL
 * Originally written by Ranier Vilela and enhanced by many contributors.
 *
 * src/bin/pg_check/pg_check.c
 * Copyright (c) 2022, PostgreSQL Global Development Group
 * ALL RIGHTS RESERVED;
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose, without fee, and without a written agreement
 * is hereby granted, provided that the above copyright notice and this
 * paragraph and the following two paragraphs appear in all copies.
 *
 * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
 * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
 * DOCUMENTATION, EVEN IF THE AUTHOR OR DISTRIBUTORS HAVE BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAS NO OBLIGATIONS TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>


static const char * progname = "pg_check";


struct S_CTX
{
        int nline;
        int nargs;
        int nchars;
        int nbrackets;
        int nkeys;
        int nperc;
        int nsfmt;
        bool quote;
        bool finish;
};

typedef struct S_CTX s_ctx;

struct S_FUNC
{
        char * function;
        char * should_string;
        char * should_char;
};

typedef struct S_FUNC s_func;


static const s_func pg_functions[] = {
        { "appendPQExpBuffer(", "should be appendPQExpBufferStr?", "should be 
appendPQExpBufferChar?" },
        { "appendStringInfo(", "should be appendStringInfoString?", "should be 
appendStringInfoChar?" },
        NULL
};


void parser_function(s_ctx * ctx, const s_func * pg_function, const char * line)
{
        const char * ptr;
        size_t len;
        size_t i;
        char ch;

        ctx->finish = false;
        ptr = line;
        len = strlen(line);
        for(i = 0; i < len; i++)
        {
                ch = ptr[i];
                if (!ctx->quote)
                {
                        if (ch == '(')
                                ctx->nbrackets++;
                        else if (ch == ')')
                                ctx->nbrackets--;
                        else if (ch == '{')
                                ctx->nkeys++;
                        else if (ch == '}')
                                ctx->nkeys--;
                        else if (ch == ';')
                        {
                                ctx->finish = true;
                                break;
                        }
                        else if (ch == ',')
                                ctx->nargs++;
                }
                if (ctx->nargs > 0)
                        if (ch == '"')
                            ctx->quote = !ctx->quote;
                if (ctx->quote)
                {
                        if (ch != '"')
                                ctx->nchars++;
                        if (ch == '%')
                                ctx->nperc++;
                        if (ch == 's' && ctx->nperc)
                        {
                                ctx->nsfmt++;
                                ctx->nperc--;
                        }
                }
        }

        /* Analyze */
        if (ctx->finish)
        {
                if (ctx->nargs < 2)
                        if (ctx->nchars == 1)
                                fprintf(stderr, "line (%d): %s\n", ctx->nline, 
pg_function->should_char);
                        else
                                fprintf(stderr, "line (%d): %s\n", ctx->nline, 
pg_function->should_string);
                else if (ctx->nargs == 2)
                        if (ctx->nsfmt == 1)
                                if (ctx->nchars == 1)
                                        fprintf(stderr, "line (%d): %s\n", 
ctx->nline, pg_function->should_char);
                                else
                                        fprintf(stderr, "line (%d): %s\n", 
ctx->nline, pg_function->should_string);
        }
}


void parser_src(FILE * f)
{
        char line[512] = {'\0'};
        s_ctx ctx = {0};
        int size = (sizeof(pg_functions) / sizeof(s_func)) - 1;
        int nline;
        int i;

        ctx.finish = true;
        i = 0;
        nline = 0;
        while(fgets(line, sizeof(line) - 1, f) != NULL)
        {
                nline++;
                if (ctx.finish)
                {
                        memset(&ctx, 0, sizeof(ctx));
                        ctx.finish = true;
                        ctx.nline = nline;

                        for(i = 0; i < size; i++)
                        {
                                const char *function;

                                function = pg_functions[i].function;
                                if (strstr(line, function) != NULL)
                                {
                                        parser_function(&ctx, &pg_functions[i], 
line);
                                        if (!ctx.finish)
                                                break;
                                }
                        }       
                }
                else
                        parser_function(&ctx, &pg_functions[i], line);
        }
}


int main(int argc, char ** argv)
{
    FILE * f;

    if (argv[0] != NULL && *argv[0] != 0) {
                progname = argv[0];
        }
    if (argc != 2)  {
        fprintf(stderr, "usage: %s source.c\n", progname);
        exit(1);
        }
    f = fopen(argv[1], "r");
    if (f == NULL) {
        exit(2);
        }
        parser_src(f);
    fclose(f);

    exit(0);
}
appendPQExpBuffer(buf, ")\n");
appendPQExpBuffer(buf, "n");
appendPQExpBuffer(buf, "client %d ", st->id);
appendPQExpBuffer(buf, "%s", "name");
appendPQExpBuffer(buf, (is_retry ?
                                                           "repeats the 
transaction after the error" :
                                                           "ends the failed 
transaction"));

Reply via email to