Thread: What does FDECL mean? (eg. function #define questions)

  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    6

    What does FDECL mean? (eg. function #define questions)

    I'm trying to port Nethack (a computer game) to another operating system but since I'm a Delphi developer I'm having a bit of trouble with some of the C code.

    A lot of the code looks like this:

    Code:
    STATIC_DCL void FDECL(redotoplin, (const char*));
    STATIC_DCL void FDECL(topl_putsym, (CHAR_P));
    STATIC_DCL void NDECL(remember_topl);
    STATIC_DCL void FDECL(removetopl, (int));
    Code:
    void FDECL((*input_func), (Widget,XEvent *,String *,Cardinal *));
    Code:
    static void FDECL(win_visible, (Widget,XtPointer,XEvent *,Boolean *));
    static void NDECL(init_standard_windows);
    The only possible #define that I could find is this:
    #define NDECL(f) f()

    What does that mean? What do all of those FDECLs mean? What does STATIC_DCL mean?

    Any help would be GREATLY appriciated

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Being curious, I did a search which eventually led me to this .
    Code:
    #ifdef HAVE_PROTOTYPES
    # define NDECL(f)        f(void)
    # define FDECL(f, p)     f p
    # ifdef HAVE_STDARG
    #  define VDECL(f, p)     f p
    # else
    #  define VDECL(f, p)     f()
    # endif
    #else
    # define NDECL(f)        f()
    # define FDECL(f, p)     f()
    # define VDECL(f, p)     f()
    #endif
    I would say that in this case, NDECL is being used with functions with no arguments, and FDECL is being used with functions that have arguments. HAVE_PROTOTYPES appears to be conditional depending on whether pre-standard C is being used.
    Code:
    #if __STDC__ - 0
    # undef  HAVE_PROTOTYPES
    # define HAVE_PROTOTYPES
    #endif
    There was no void in pre-standard C.

    And the STATIC_DECL is a conditionally-static declaration. That is, given certain precompiler conditions, the function may be declared as static or it may not.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    6
    Thanks for the reply!

    How do I read the syntax for functions such as:
    # define FDECL(f, p) f p

    Is there a good tutorial or FAQ on #define's in C?


    In Delphi there is a concept of function prototypes (not sure if that is the correct phrase), but it lets you do stuff like:

    Code:
    type
      func : function(a, b: String);
    end;
    Then you can declare functions of type func or even an array of func.

    Is this sort of what FDECL/NDECL/VDECL are doing?

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    A #define does macro replacement, text for text. If you ran this through the preprocessor,
    Code:
    extern int    FDECL(cstrcmp,(CONST char *s, CONST char *t));
    it would become this.
    Code:
    extern int    cstrcmp (CONST char *s, CONST char *t);
    (And the CONST is likely to conditionally be const or nothing.)

    The macros appear to be a way in which this project attempts to be compatible a number of systems.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    Apr 2006
    Posts
    6
    Ahh, gotcha!

    What about something like this: (?)

    Code:
    E void FDECL(m_unleash, (struct monst *,BOOLEAN_P));
    I now understand that it would become:

    E void m_unleash (struct monst *, BOOLEAN_P)

    ...but what does the E mean?

    Also, one last question about the following code. Ignore what it's doing, my question has to do with the function declaration syntax...

    Code:
    #ifndef WIN32CON
    /* fatal error */
    /*VARARGS1*/
    void
    error VA_DECL(const char *,s)
    	char buf[BUFSZ];
    	VA_START(s);
    	VA_INIT(s, const char *);
    	/* error() may get called before tty is initialized */
    	if (iflags.window_inited) end_screen();
    	if (!strncmpi(windowprocs.name, "tty", 3)) {
    		buf[0] = '\n';
    		(void) vsprintf(&buf[1], s, VA_ARGS);
    		Strcat(buf, "\n");
    		msmsg(buf);
    	} else {
    		(void) vsprintf(buf, s, VA_ARGS);
    		Strcat(buf, "\n");
    		raw_printf(buf);
    	}
    	VA_END();
    	exit(EXIT_FAILURE);
    }
    #endif
    VA_DECL is declared like this:
    Code:
    # define VA_DECL(typ1,var1)	(typ1 var1, ...) { va_list the_args;
    // or  (depending on some #define)
    #  define VA_DECL(typ1,var1)	(va_alist) va_dcl {\
    		va_list the_args; typ1 var1;
    What confuses me is that the function above (void error) is that it looks like it's being started without an opening brace. Is that taken care of from the #define macro? Is the #define macro also declaring a variable? It looks like the macro needs four parameters but is only being passed in two...

    Sorry for all of the questions (and code). I really, really appriciate your help!

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by sofakng
    What about something like this: (?)

    Code:
    E void FDECL(m_unleash, (struct monst *,BOOLEAN_P));
    I now understand that it would become:

    E void m_unleash (struct monst *, BOOLEAN_P)

    ...but what does the E mean?
    I thought I saw it somewhere (conditionally?) #defined as extern.

    Quote Originally Posted by sofakng
    Also, one last question about the following code. Ignore what it's doing, my question has to do with the function declaration syntax...

    Code:
    #ifndef WIN32CON
    /* fatal error */
    /*VARARGS1*/
    void
    error VA_DECL(const char *,s)
    	char buf[BUFSZ];
    	VA_START(s);
    	VA_INIT(s, const char *);
    	/* error() may get called before tty is initialized */
    	if (iflags.window_inited) end_screen();
    	if (!strncmpi(windowprocs.name, "tty", 3)) {
    		buf[0] = '\n';
    		(void) vsprintf(&buf[1], s, VA_ARGS);
    		Strcat(buf, "\n");
    		msmsg(buf);
    	} else {
    		(void) vsprintf(buf, s, VA_ARGS);
    		Strcat(buf, "\n");
    		raw_printf(buf);
    	}
    	VA_END();
    	exit(EXIT_FAILURE);
    }
    #endif
    VA_DECL is declared like this:
    Code:
    # define VA_DECL(typ1,var1)	(typ1 var1, ...) { va_list the_args;
    // or  (depending on some #define)
    #  define VA_DECL(typ1,var1)	(va_alist) va_dcl {\
    		va_list the_args; typ1 var1;
    What confuses me is that the function above (void error) is that it looks like it's being started without an opening brace. Is that taken care of from the #define macro? Is the #define macro also declaring a variable? It looks like the macro needs four parameters but is only being passed in two...
    [I added the highlighting.]

    The opening brace is part of the macro. And these are the two parameters it takes. The bold stuff is the replacement list.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User
    Join Date
    Apr 2006
    Posts
    6
    With this line:

    # define VA_DECL(typ1,var1) (va_alist) va_dcl {\
    va_list the_args; typ1 var1;

    Doesn't typ1 and var1 need to be enclosed with parenthesis to be replaced with the variable passed in? ...otherwise I thought it's replaced with the literal string "typ1";

    So in other words, let's say I called the function like this:

    VA_DECL(hello, goodbye)

    I would expect it to be replaced like this:

    (va_list) va_dcl {
    va_list the_args; typ1 var1;

    ...instead of:

    (va_list) va_dcl {
    va_list the_args; hello goodbye;

    At least according to a tutorial I've read about #define's. Also, can a #define have other defines inside of it? It looks like va_dcl might be yet another #define inside the #define... (confusing...)

  8. #8
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by sofakng
    I would expect it to be replaced like this:

    (va_list) va_dcl {
    va_list the_args; typ1 var1;

    ...instead of:

    (va_list) va_dcl {
    va_list the_args; hello goodbye;
    It would be the latter.
    Code:
    (va_list) va_dcl {
      va_list the_args; hello goodbye;
    Quote Originally Posted by sofakng
    At least according to a tutorial I've read about #define's. Also, can a #define have other defines inside of it? It looks like va_dcl might be yet another #define inside the #define... (confusing...)
    Can you post a link to the tutorial?

    Often parentheses are used with macros because it is just a text replacement. Things may be dandy with simple things, but results may be surprising with more complicated expressions.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with Bitmap Display
    By The Brain in forum Windows Programming
    Replies: 7
    Last Post: 03-23-2009, 05:33 AM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM