Macro to assign unique number to a source file

Discussion in 'C Programming' started by celephicus, Jul 22, 2010.

  1. celephicus

    celephicus Guest

    Greetings

    I use a macro below to get a guaranteed unique number to identify
    source files for asserts in a system with very little memory. This
    works fine, but sometimes braindead compilers do not optimise away the
    dummy function, so it appears in the object file. Is there another way
    of checking for no duplicates in "C"?

    #define FILENUM(n) \
    void errorHandlerDummyFunctionForCheckingFileNumber_##n(void) {} \
    enum { F_NUM = (n) }

    TomH
    celephicus, Jul 22, 2010
    #1
    1. Advertising

  2. celephicus

    Thad Smith Guest

    celephicus wrote:

    > I use a macro below to get a guaranteed unique number to identify
    > source files for asserts in a system with very little memory. This
    > works fine, but sometimes braindead compilers do not optimise away the
    > dummy function, so it appears in the object file. Is there another way
    > of checking for no duplicates in "C"?
    >
    > #define FILENUM(n) \
    > void errorHandlerDummyFunctionForCheckingFileNumber_##n(void) {} \
    > enum { F_NUM = (n) }


    I would create a separate header file
    filenums.h:
    enum {
    FILEA=1,
    FILEB=2,
    FILEC=3};

    In file filea.c:
    #include "filenums.h"
    #define F_NUM FILEA

    Keep the entries in filenums.h in numeric order, which allows you to easily
    verify uniqueness manually. You could, of course, omit the explicit enum
    assignment, but then the numeric value isn't obvious. You could also write a
    utility to verify uniqueness and run it as part of the build process.

    --
    Thad
    Thad Smith, Jul 22, 2010
    #2
    1. Advertising

  3. celephicus

    Ian Collins Guest

    On 07/22/10 12:57 PM, celephicus wrote:
    > Greetings
    >
    > I use a macro below to get a guaranteed unique number to identify
    > source files for asserts in a system with very little memory. This
    > works fine, but sometimes braindead compilers do not optimise away the
    > dummy function, so it appears in the object file. Is there another way
    > of checking for no duplicates in "C"?


    One bodge I have used on small system is to log the PC and determine the
    function form the map file..

    --
    Ian Collins
    Ian Collins, Jul 22, 2010
    #3
  4. celephicus

    celephicus Guest


    >
    > I would create a separate header file
    > filenums.h:
    > enum {
    >    FILEA=1,
    >    FILEB=2,
    >    FILEC=3};
    >
    > In file filea.c:
    > #include "filenums.h"
    > #define F_NUM FILEA
    >
    >


    Good idea, because the information is defined in exactly one place,
    not spread over all source files. Plus I can easily find the relevant
    file relating to a filenumber from one source file, previously I was
    using "grep FILENUM *.c". And any decent scripting language can
    autogenerate the enum in about 3 lines.

    TomH
    celephicus, Jul 22, 2010
    #4
  5. celephicus

    Eric Sosman Guest

    On 7/21/2010 8:57 PM, celephicus wrote:
    > Greetings
    >
    > I use a macro below to get a guaranteed unique number to identify
    > source files for asserts in a system with very little memory. This
    > works fine, but sometimes braindead compilers do not optimise away the
    > dummy function, so it appears in the object file. Is there another way
    > of checking for no duplicates in "C"?
    >
    > #define FILENUM(n) \
    > void errorHandlerDummyFunctionForCheckingFileNumber_##n(void) {} \
    > enum { F_NUM = (n) }


    The errorHandler... thing is to help you detect accidental re-use
    of identical `n' values in different files, is that it? Then if the
    compiler were to remove the function, what would happen to your error
    detection?

    Also, calling a compiler "braindead" because it compiles a function
    you told it to compiler seems a little harsh. Seems to me the smell of
    cranial necrosis arises from a different source entirely ...

    --
    Eric Sosman
    lid
    Eric Sosman, Jul 24, 2010
    #5
  6. celephicus

    Shao Miller Guest

    I don't know if you might be interested in counting in headers or not,
    but:
    -----
    /* foo.h */
    #define MAGIC_COUNT_NEXT foo
    #include "magic_count.h"
    #define MAGIC_COUNT_CUR foo

    /* ... */

    /* End of foo.h */
    -----
    /* bar.h */
    #define MAGIC_COUNT_NEXT bar
    #include "magic_count.h"
    #define MAGIC_COUNT_CUR bar

    /* ... */

    /* End of bar.h */
    -----
    /* baz.h */
    #define MAGIC_COUNT_NEXT baz
    #include "magic_count.h"
    #define MAGIC_COUNT_CUR baz

    /* ... */

    /* End of baz.h */
    -----
    #ifdef MAGIC_COUNT_USAGE
    /*
    * magic_count.h (C) 2010 Shao Miller
    * Use and adaptation permitted, if credit for origin is included.
    *
    * Usage:
    *
    * #define MAGIC_COUNT_NEXT foo
    * #include "magic_count.h"
    * #define MAGIC_COUNT_CUR foo
    *
    * Then MAGIC_COUNT will be #defined to a size_t
    * integer constant expression
    */
    #endif

    #ifndef MAGIC_COUNT_CUR
    #ifdef MAGIC_COUNT
    #error "You forgot to #define MAGIC_COUNT_CUR after #including"
    #else
    #define MAGIC_COUNT 0
    #endif
    #define MAGIC_COUNT_FIRST 1
    #define MAGIC_COUNT_PASTE2(x,y) x ## y
    #define MAGIC_COUNT_PASTE(x,y) MAGIC_COUNT_PASTE2(x,y)
    #endif

    #ifndef MAGIC_COUNT_NEXT
    #error "You forgot to #define MAGIC_COUNT_NEXT before #inlcuding"
    #endif

    #ifdef MAGIC_COUNT_INC
    #error "You already have MAGIC_COUNT_INC #defined"
    #endif

    #define MAGIC_COUNT_INC() \
    \
    struct MAGIC_COUNT_PASTE(MAGIC_COUNT_S_, MAGIC_COUNT_NEXT) {\
    char (*count)[MAGIC_COUNT + 1]; }

    MAGIC_COUNT_INC();

    #if MAGIC_COUNT_FIRST
    #undef MAGIC_COUNT
    #define MAGIC_COUNT \
    \
    (sizeof \
    *(((struct MAGIC_COUNT_PASTE(MAGIC_COUNT_S_,MAGIC_COUNT_CUR) *)0)-
    >count)\

    )
    #undef MAGIC_COUNT_FIRST
    #endif

    #undef MAGIC_COUNT_INC
    #undef MAGIC_COUNT_NEXT
    #ifdef MAGIC_COUNT_CUR
    #undef MAGIC_COUNT_CUR
    #endif
    /* End of magic_count.h */
    -----
    /* main.c */
    #include "foo.h"
    #include "bar.h"
    #include "baz.h"

    int main(void) {
    return (int)MAGIC_COUNT;
    }

    /* End of main.c */
    -----

    It might be fun for counting purposes.
    Shao Miller, Jul 28, 2010
    #6
  7. celephicus

    Shao Miller Guest

    Probably won't be submitting that for any obfuscated code contests, so
    'typedef'fing a simple 'char[XXX]' type and taking its 'sizeof' would
    be less challenging to read than the fun 'struct' business. Heheh.
    Shao Miller, Jul 28, 2010
    #7
  8. Thad Smith <> wrote:
    > celephicus wrote:
    > > I use a macro below to get a guaranteed unique number
    > > to identify source files for asserts in a system with
    > > very little memory.


    Not the usual assert() macro then?! Do you really need a
    number? What do you do with it? What's wrong with __FILE__?

    > > This works fine, but sometimes braindead compilers do
    > > not optimise away the dummy function,


    Well, if you're braindead enough to put in the dummy function... ;)

    > > so it appears in the object file. Is there another way
    > > of checking for no duplicates in "C"?
    > >
    > > #define FILENUM(n) \
    > >     void errorHandlerDummyFunctionForCheckingFileNumber_##n
    > > (void) {} \
    > >     enum { F_NUM = (n) }

    >
    > I would create a separate header file
    > filenums.h:
    > enum {
    >    FILEA=1,
    >    FILEB=2,
    >    FILEC=3};
    >
    > In file filea.c:
    > #include "filenums.h"
    > #define F_NUM FILEA
    >
    > Keep the entries in filenums.h in numeric order, which
    > allows you to easily verify uniqueness manually. You
    > could, of course, omit the explicit enum assignment, but
    > then the numeric value isn't obvious.  You could also
    > write a utility to verify uniqueness and run it as part
    > of the build process.


    Built in uniqueness...

    /* begin header */

    #define FILE_NAMES(M,_) \
    M( FILE_A, "FileA.c" ) _ \
    M( FILE_B, "FileB.c" ) _ \
    M( FILE_C, "FileC.c" ) _ \
    M( FILE_D, "FileD.c" )

    #define COMMA ,
    #define SEMI_COLON ;
    #define AS_ENUM(a,b) a

    enum { FILE_NULL=0, FILE_NAMES(AS_ENUM, COMMA) };

    /* end header */

    #include <stdio.h>
    /* include above header in required files */

    #define AS_PRINTF(a,b) printf("%s,%d,\"%s\"\n", #a, a, b)

    int main(void)
    {
    FILE_NAMES(AS_PRINTF, SEMI_COLON);
    return 0;
    }

    Assigned values validator...

    /* begin header */

    #define FILE_NAMES(M,_) \
    M( FILE_A, 1, "FileA.c" ) _ \
    M( FILE_B, 2, "FileB.c" ) _ \
    M( FILE_C, 3, "FileC.c" ) _ \
    M( FILE_D, 2, "FileD.c" )

    #define COMMA ,
    #define SEMI_COLON ;
    #define AS_ENUM(a,b,c) a = b

    enum { FILE_NULL=0, FILE_NAMES(AS_ENUM, COMMA) };

    /* end header */

    #include <stdio.h>
    /* include above header in required files */

    #define AS_ARRAY(a,b,c) { #a, a }

    struct {
    const char *enum_name;
    int value;
    } array[] = { FILE_NAMES(AS_ARRAY, COMMA) };

    #define countof(x) (sizeof(x) / sizeof*(x))

    int main(void)
    {
    int okay = 1;
    size_t i, j;

    for (i = 0; i < countof(array) - 1; i++)
    for (j = i + 1; j < countof(array); j++)
    if (array.value == array[j].value)
    {
    printf("%s and %s both have value %d\n",
    array.enum_name,
    array[j].enum_name,
    array.value);
    okay = 0;
    }

    if (okay) puts("okay!");

    return 0;
    }

    --
    Peter
    Peter Nilsson, Jul 28, 2010
    #8
  9. celephicus

    Shao Miller Guest

    On Jul 27, 10:08 pm, Shao Miller <> wrote:
    > Probably won't be submitting that for any obfuscated code contests, so
    > 'typedef'fing a simple 'char[XXX]' type and taking its 'sizeof' would
    > be less challenging to read than the fun 'struct' business.  Heheh.


    Or adding to an 'enum' might be even simpler than even that.
    Shao Miller, Jul 28, 2010
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    334
  2. Replies:
    3
    Views:
    550
    Bo Persson
    Aug 15, 2007
  3. ToshiBoy
    Replies:
    6
    Views:
    842
    ToshiBoy
    Aug 12, 2008
  4. Replies:
    12
    Views:
    166
    Jorge
    Apr 8, 2009
  5. Token Type
    Replies:
    9
    Views:
    350
    Chris Angelico
    Sep 9, 2012
Loading...

Share This Page