Как преобразовать код C для старой Visual Studio 2005, особенно исходный код TinyExpr - PullRequest
0 голосов
/ 23 октября 2019

Я хочу преобразовать исходный код TinyExpr (https://github.com/codeplea/tinyexpr) в C-совместимый код для Visual Studio 2005 (я думаю, что это C89 / 90-совместимый). В частности, у меня есть проблема для преобразования этого макроса в(присутствует в tinyexpr.c):

#define NEW_EXPR(type, ...) new_expr((type), (const te_expr*[]){__VA_ARGS__})

с:

typedef struct te_expr {
    int type;
    union {double value; const double *bound; const void *function;};
    void *parameters[1];
} te_expr;

static te_expr *new_expr(const int type, const te_expr *parameters[]) {
 ...
}

static te_expr *base(state *s) {
  ...
}

Проблема возникает в вызове: NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, base(s));, где у меня есть:

ошибка C2059: ошибка синтаксиса: '{'

1 Ответ

1 голос
/ 23 октября 2019

Как я сказал в комментарии, в старом компиляторе действительно нет хорошего способа сделать это.

Один из возможных способов - использовать функцию-обертку vararg, которая динамически создает массив, вызывая реальный new_exprфункция, а затем освободить временный массив.

Возможно, что-то вроде

te_expr *new_expr_va(const int type, ...) {
    re_expr *result = NULL;  /* The resulting expression structure to return */
    size_t argument_count = 0;  /* The number of te_expr arguments passed */

    /*
     * We do two passes over the arguments, once to get the number of them,
     * and once to get the actual values.
     */

    /* First get the number of arguments */
    {
        va_list va;

        va_start(va, type);

        /* Loop until we get a null pointer */
        while (va_arg(va, te_expr *) != NULL)
            ++argument_count;

        va_end(va);
    }

    /* Now allocate the array */
    te_expr **parameters = malloc(argument_count * sizeof(te_expr *));

    /* And populate the array */
    {
        va_list va;
        size_t index = 0;
        te_expr *expr;

        va_start(va, type);

        /* Get all arguments and add to the allocated array */
        while ((expr = va_arg(va, te_expr *)) != NULL)
            parameters[index++] = expr;

        va_end(va);
    }

    /* Now we call the actual function */
    result = new_expr(type, parameters);

    /* Free the memory we allocated for the array */
    free(parameters);

    /* And return the result */
    return result;
}

Может быть использовано, например,

/* Argument list must be terminated by a NULL */
new_expr_va(TE_FUNCTION1 | TE_FLAG_PURE, base(s), NULL);

Обратите внимание, что все это не проверено и не 'не может быть никакой проверки ошибок.

...