Thread: Never seen this syntax before. Help?

  1. #1
    Registered User
    Join Date
    May 2006
    Posts
    182

    Never seen this syntax before. Help?

    I'm taking a look at all the good stuff GNU has made and I ran into something I have never seen before.

    For example line 166 in binutils-2.9.1/bin-utils/nm.c you have this

    Code:
    /* Support for different output formats.  */
    struct output_fns
      {
    
        /* Print the name of an object file given on the command line.  */
        void (*print_object_filename) PARAMS ((char *filename));
    
        /* Print the name of an archive file given on the command line.  */
        void (*print_archive_filename) PARAMS ((char *filename));
    
        /* Print the name of an archive member file.  */
        void (*print_archive_member) PARAMS ((char *archive, CONST char *filename));
    
        /* Print the name of the file (and archive, if there is one)
           containing a symbol.  */
        void (*print_symbol_filename) PARAMS ((bfd * archive_bfd, bfd * abfd));
    
        /* Print a line of information about a symbol.  */
        void (*print_symbol_info) PARAMS ((symbol_info * info, bfd * abfd));
    
      };
    or this on line 286
    Code:
    static void
    usage (stream, status)
         FILE *stream;
         int status;
    {
    What is "PARAMS"? What is "usage"?
    How are there parameters outside of the parameter area such as "FILE *stream" in the second example.

    These don't look like regular functions to me if they are that.
    Last edited by yougene; 06-01-2009 at 04:59 PM.

  2. #2
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    I don't know about PARAMS, but usage looks like an ordinary function to me. That's exactly the old-style (pre-ANSI C) syntax we've been discussing in my "Strange main function" thread.
    "FILE *stream; int status;" declare the types of the function parameters.

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    PARAMS is defined either in the file or in a header, so you should be able to find it; but what it does is allow you to switch between old-style K&R function declarations and honest-to-goodness prototypes. So in K&R mode that last function would be
    Code:
    void (*print_symbol_info);
    and in ANSI mode would be
    Code:
    void (*print_symbol_info) (symbol_info * info, bfd * abfd);

  4. #4
    Registered User
    Join Date
    Feb 2003
    Posts
    596
    Defined in binutils-[ver]/include/ansidecl.h:
    Code:
    #define PARAMS(ARGS)		ARGS

  5. #5
    Registered User
    Join Date
    May 2006
    Posts
    182
    Thanks this has all been insightful.

    Let me show what I do understand so far so maybe someone can fill in the gaps.


    void (*print_object_filename) PARAMS ((char *filename));
    for example


    void indicates I'm declaring a pointer which I'm assuming is going to be called (*print_object_filename).

    PARAMS gets replaced with ARGS before compilation so we really have
    void (*print_object_filename) ARGS ((char *filename));

    and then what follows is the parameters of the function.


    It's still a little hazy though.
    Is this a declaration or a prototype?
    I'm not quite following your reasoning tabstop. In your second code snippet what happens to the PARAM? It looks like you just took it out of the code.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    void means "this function doesn't return anything". "(*print_object_filename)" means "this is a pointer to a function".

    As to the other, your search and replace skills need work. Look at the definition:
    Code:
    #define PARAMS(ARGS)		ARGS
    This means that "PARAMS(ARGS)" gets replaced by "ARGS" where, since this is a pseudofunction, ARGS is whatever you actually type in inside the parentheses. Since you typed in "(char *filename)" inside the parentheses, that's what ARGS is -- "(char *filename)". So that is what the macro expands to.

    In fact, if you look at the definition of the macro, PARAMS gets taken out of the code.

  7. #7
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    They're function pointers, which, as the name suggests, are pointers that point to functions.

    You probably have something like:
    Code:
    #if __STDC__
    #define PARAMS(p) p
    #else
    #define PARAMS(p) ()
    #endif
    So if you're using standard C (that is, prototypes are available), you get:
    Code:
    void (*print_object_filename)(char *filename);
    and if you're not, you get:
    Code:
    void (*print_object_filename)();
    It's a bit difficult at first to unwind the declarations, but the prototyped one is this: print_object_filename is a pointer to a function that takes a char* and returns nothing. So you can assign to it a function (pointer) that matches the prototype:
    Code:
    void function(char *filename)
    {
    }
    ...
    void (*f)(char *);
    f = function;
    f("file"); /* this is now the same as ... */
    function("file");
    By putting function pointers inside of a struct you can have C act kind of like an object oriented language.

  8. #8
    Registered User
    Join Date
    May 2006
    Posts
    182
    Ahhh ok. So I actually have a pseudo-function
    PARAMS ((char *filename))
    which gets converted to ARGS which really just means whatever is inside the parameter.


    What purpose is doing all this serving? It seems redundant and cryptic to me right now.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by yougene View Post
    Ahhh ok. So I actually have a pseudo-function
    PARAMS ((char *filename))
    which gets converted to ARGS which really just means whatever is inside the parameter.


    What purpose is doing all this serving? It seems redundant and cryptic to me right now.
    Because there are STILL compilers around [or were around when the project was created] that do not accept ANSI code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. more then 100errors in header
    By hallo007 in forum Windows Programming
    Replies: 20
    Last Post: 05-13-2007, 08:26 AM
  2. We Got _DEBUG Errors
    By Tonto in forum Windows Programming
    Replies: 5
    Last Post: 12-22-2006, 05:45 PM
  3. Using VC Toolkit 2003
    By Noobwaker in forum Windows Programming
    Replies: 8
    Last Post: 03-13-2006, 07:33 AM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM