Compile time error: 'expected expression before '*' while using va_list

Viewed 12

This is a hefty program so I will try to give the relevant code. Basically I am trying to use 'va_args in a C program (I am slightly proficient in C). The issue is I get this error when I compile:

deo.c:192:38: error: expected expression before ‘DEO_Button’
192 |                 temp = va_args(args, DEO_Button*);

Here is my header file:

#ifndef         DEO_H
#define         DEO_H

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <ncurses.h>
#include <form.h>
#include <menu.h>

#include "widgets.h"

/* Self-defined colors: 0b<Magenta><Yellow><Cyan><Intensity?><Intensity?><Blue><Green><Red> */

#define         DEO_WHITE   0b00001111
#define         DEO_DGREY   0b00001000
#define         DEO_LGREY   0b11110111
#define         DEO_LGREEN  0b00000010
#define         DEO_DCYAN   0b00000110
#define         DEO_LCYAN   0b00001110
#define         DEO_BROWN   0b01010000

/* General output types for a struct member's state */
#define         DEO_GET_COLOR           1300
#define         DEO_GET_S0      1360
#define         DEO_GET_S1      1361
#define         DEO_GET_S2      1362
#define         DEO_GET_S3      1363
#define         DEO_SET_COLOR           DEO_GET_COLOR
#define         DEO_SET_S0      DEO_GET_S0
#define         DEO_SET_S1      DEO_GET_S1
#define         DEO_SET_S2      DEO_GET_S2
#define         DEO_SET_S3      DEO_GET_S3

/* Macro allows overloading 'deo_within' function */
#define deo_within(x, y, z) \
        _Generic( x,DEO_Window:    _a_deo_within, \
                    WINDOW*: _b_deo_within) \
                    (x,y,z)

/* Allows us to count the number of arguments in our deo_switch_focus function */
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define deo_switch_focus(...) deo_switch_focus(NARGS(__VA_ARGS__) - 1, __VA_ARGS__)

/* Inits, creates, and destroys */
int main(void);
int deo_init(void);
int action_bl(DEO_Button*);
int action_br(DEO_Button*);

/* Internal Functions (functions that just don't belong anywhere else): see intern.c */
int _a_deo_within(DEO_Window, int, int);
int _b_deo_within(WINDOW*, int, int);
static int (deo_switch_focus)(int, DEO_Button*, ...);
int deo_get_bits(uint8_t, const int);
int deo_set_bits(uint8_t*, const int, uint8_t);
int deo_assign_rect(DEO_Rect*, int, int, int, int);
int deo_warn_text(char*, ...);
int deo_clear_warn_text(void);

#endif

Here is the C file with my main function in it:

#include "../include/deo.h"

int main()
{
    char title[] = "Project Demeter (deo) v0.1.0a";
    int c = 0;
    int len = 0;
    int x = 0, y = 0, iter = 0;
    DEO_Button butt_b, new_b, test_b;
    DEO_Window main_w, title_w, menubar_w, lside_w;
    MEVENT event;

    /* { X, Y, W, H}  Define out window and widget dimensions */
    deo_assign_rect(&main_w.rect, 0, 0, 0, 0);
    deo_assign_rect(&menubar_w.rect, 0, 4, 0, 1);
    deo_assign_rect(&lside_w.rect, 0, 2, 30, 0);
    deo_assign_rect(&title_w.rect, 0, 2, 0, 1);
    deo_assign_rect(&butt_b.rect, 7, 7, 0, 0);
    deo_assign_rect(&new_b.rect, 30, 20, 0, 0);
    
    if(deo_init() < 1)
        return -1;

    /* Move the windows and widgets to their places */
    getmaxyx(stdscr, main_w.rect.h, main_w.rect.w);
    title_w.rect.w      = main_w.rect.w;
    menubar_w.rect.w    = main_w.rect.w;
    lside_w.rect.h      = main_w.rect.h - 2;

    /* Create our widgets */
    deo_create_window(&main_w, "\0", 1);
    deo_create_window(&menubar_w, "\0", 1);
    deo_create_window(&lside_w, "\0", 1);
    deo_create_window(&title_w, title, 1); /* Title should always be showing; send to top */
    deo_create_button(&butt_b, &lside_w, "Nicholas", 5);
    deo_create_button(&new_b, &main_w, "OK", 5);

    /* Define our button actions */
    butt_b.action_clkdwn = action_bl;   /* assign our function to the left-clicked function call */
    butt_b.action_r_clkdwn = action_br; /* assign our function to the right-clicked function call */
    new_b.action_clkdwn = action_bl;    /* assign our function to the left-clicked function call */
    new_b.action_r_clkdwn = action_br;  /* assign our function to the right-clicked function call */
    deo_set_bits(&new_b.state, DEO_SET_FOCUS, true);    /* This is our 'default' button */

    /* Draw our texts */
    attron(COLOR_PAIR(2));
        mvwprintw(stdscr, 1, 1, "Time: 04:20:00");
        mvwprintw(stdscr, 1, main_w.rect.w / 4, "Date: 06-06-06");
        mvwprintw(stdscr, 1, ( (3 * main_w.rect.w) / 4 ) - 20, "User: NJStatic ");
        mvwprintw(stdscr, 1, main_w.rect.w - 21, "Last Login: 04:20:00");
    attroff(COLOR_PAIR(2));
    
    /* Start our instance */
    do
    {
        c = getch();
        switch(c)
        {
            case KEY_MOUSE:
                curs_set(2);
                if(getmouse(&event) == OK)
                {
                    x = event.x;
                    y = event.y;

                    /*deo_warn_text("Mouse: (%d, %d)", x, y); */
                    deo_update_button(&butt_b, &event);
                    deo_update_button(&new_b, &event);
                    move(y,x);
                }
                break;
            case '\t':
                deo_switch_focus(&new_b, &butt_b, &test_b);
            default:
                
                break;
        }

        /* A refresh of our buttons do not go here (they are refreshed using the update functions) */
        wrefresh(main_w.window);
        wrefresh(menubar_w.window);
        wrefresh(lside_w.window);
        wrefresh(title_w.window);
        refresh();

    }while(c != '\n');

    /* Clean-up */
    deo_delete_button(&butt_b);
    deo_delete_button(&new_b);
    deo_delete_window(&menubar_w.window);
    deo_delete_window(&lside_w.window);
    deo_delete_window(&title_w.window);
    deo_delete_window(&main_w.window);

    printf("\033[?1003l\n"); /* Disable term mouse movement events */
    clear();
    endwin();
    return 0;
}

/* Initialize NCurses, colors, and the mouse */
int deo_init()
{
    /* Start curses mode */
    if(initscr() == NULL)
         return -5;

    cbreak();               /* Disable's line buffering (otherwise input is on hold until a newline is made) */
    noecho();               /* Do not print what is typed */
    keypad(stdscr, true);   /* Enables mouse, function keys, and arrows */
    curs_set(0);            /* Sets the cursor style to invisible */

    /* Does our TERM have color capabilities */
    if(has_colors() == false)
    {
        endwin();
        printf("error: current terminal does not support color info\n");
        return -2;
    }
    
    /* Setting up our palette */
    start_color();
    init_pair(0, DEO_WHITE, COLOR_BLACK);   /* Default */
    init_pair(1, DEO_WHITE, DEO_DGREY);     /* Windows and the menu */
    init_pair(2, COLOR_WHITE, COLOR_BLACK); /* Date, logged in, time, etc */
    init_pair(3, DEO_WHITE, COLOR_RED);     /* Error */
    init_pair(4, DEO_LGREEN, DEO_LGREEN);   /* Focus widgets */
    init_pair(5, COLOR_BLACK, DEO_LGREEN);     /* Button Perimeter */
    init_pair(6, DEO_WHITE, COLOR_BLACK);       /* When the button is clicked down */

    /* Setup for mouse input */
    printf("\033[?1003h\n"); /* Makes the terminal report mouse events */
    fflush(stdout);
    mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL);
    mouseinterval(0);

    refresh();
    return 1;
}

int deo_assign_rect(DEO_Rect* rect, int x, int y, int w, int h)
{
    rect->x = x;
    rect->y = y;
    rect->w = w;
    rect->h = h;
    return 10;
}

/* deo_within(): see intern.c */

/* Our function call for left-clicking on a button */
int action_bl(DEO_Button* butt)
{
    if(butt == 0)
        return -10;
    
    deo_warn_text("Left Button Clicked!");

    return 10;
}

/* Our function call for right-clicking on a button */
int action_br(DEO_Button* butt)
{
    if(butt == 0)
        return -10;

    deo_clear_warn_text();
    return 10;
}

/* Puts buttons into focus by switching the focus to the first argument of DEO_Button */
static int (deo_switch_focus)(int count, DEO_Button* butt, ...)
{
    DEO_Button* temp = 0;
    va_list args;
    int iter = 0;

    if(butt == NULL)
    {
        printf("error while switching focus for buttons\n");
        return -1;
    }

    va_start(args, butt);
    assert(args != NULL);

    for(;iter < count; iter++)
    {
        temp = va_args(args, DEO_Button*);
        deo_set_bits(&temp->state, DEO_SET_FOCUS,false);
    }
    deo_set_bits(&butt->state, DEO_SET_FOCUS, true);

    va_end(args);
    return 10;
}

When I try to compile a separate program below it compiles just fine:

#include <stdio.h>
#include <stdarg.h>

#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define test(...) test(NARGS(__VA_ARGS__) - 1, __VA_ARGS__)

typedef struct rect_t
{
    int x;
    int y;
    int w;
    int h;
} Rect;

static void (test)(int, Rect, ...);
int main(void);

static void (test)(int count, Rect rect, ...)
{
    va_list args;
    Rect temp;
    int iter = 0;

    va_start(args, rect);
    for(;iter < count; iter++ )
    {
        temp = va_arg(args, Rect);
        temp.x = 5;
        temp.y = 5;
        temp.w = 10;
        temp.h = 10;
    }
    va_end(args);
}

int main()
{
    Rect a, b, c;

    test(a, b, c);

    printf("Default Values should be {%d, %d, %d, %d}\n", c.x, c.y, c.w, c.h);
    return 0;
}

I have a feeling that there is a problem with locating the declaration of va_args() even though I have included it in my main header file. It is possible that the macro used to calculate the number of arguments is affecting the program in some way(I am quite new to macro implementation) I am not sure how to get it to work. The code makes sense to me, I hope I am missing something here! Thank you very much for reading my post. This is my first one!!!

0 Answers
Related