It is currently Mon Nov 18, 2019 2:34 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Fri Nov 08, 2019 10:22 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1908
I have some C source code (in cc65) where I connect variable names by macros:
Code:
#define DECLARE_NUMBER_WITH_POSTFIX()\
   int Number##CurrentPostfix

#define CurrentPostfix A
DECLARE_NUMBER_WITH_POSTFIX();

void Function(void)
{
   NumberA = 1;
}

The problem is: In this case, the variable is still called NumberCurrentPostfix and not NumberA.

I need to do this for it to work:
Code:
#define DECLARE_NUMBER_WITH_POSTFIX__(postfix)\
   int Number##postfix

#define DECLARE_NUMBER_WITH_POSTFIX_(postfix)\
   DECLARE_NUMBER_WITH_POSTFIX__(postfix)

#define DECLARE_NUMBER_WITH_POSTFIX()\
   DECLARE_NUMBER_WITH_POSTFIX_(CurrentPostfix)

#define CurrentPostfix A
DECLARE_NUMBER_WITH_POSTFIX();

void Function(void)
{
   NumberA = 1;
}


Now, I have a whole bunch of those macros. And everytime, I have to declare a group of three that call each other.

Is there a way to shorten this?

Either if Number##CurrentPostfix could directly be converted to NumberA somehow.

Or if I declare one singular global macro that needs to be declared in this group of three, but all other macros can be declared once and they simply call this global macro.

For example, if this would work: Number##MACRO_VALUE(CurrentPostfix) and only MACRO_VALUE would have been declared in a group.


By the way, the connection of names can be completely different each time.
So, just declaring a macro VALUE(baseName, postfix) and then to call int VALUE(Number, CurrentPostfix); in my other macros wouldn't be enough.

Because sometimes I also have stuff similar to this: CurrentType##Data_b##CurrentBankName##CurrentBankNumber which would then be turned to CharacterData_bChr1.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Thu Nov 14, 2019 4:10 pm 
Offline
User avatar

Joined: Sat Aug 31, 2019 2:12 pm
Posts: 23
I'm a little bit confused by your post, but isn't this enough?

Code:
#define DECLARE_NUMBER_WITH_POSTFIX(postfix) \
    int Number##postfix

DECLARE_NUMBER_WITH_POSTFIX(A);

Live: https://godbolt.org/z/3qXXQY

I've been doing a lot of similar stuff with macros lately, maybe this can help:

sprite.h
Code:
#define DECLARE_SPRITE(sprite_name, num_animations, total_num_frames) \
  extern const byte sprite_##sprite_name##_animations[num_animations][3]; \
  extern const byte sprite_##sprite_name##_frame_data[total_num_frames][2]; \
  extern const Sprite sprite_##sprite_name; \
  enum { sprite_##sprite_name##_##n_animations = num_animations }; \
  enum { sprite_##sprite_name##_##n_frames = total_num_frames }

#define CREATE_SPRITE(sprite_name, info, data) \
  const byte sprite_##sprite_name##_animations[sprite_##sprite_name##_##n_animations][3] = info; \
  const byte sprite_##sprite_name##_frame_data[sprite_##sprite_name##_##n_frames][2] = data; \
  const Sprite sprite_##sprite_name = { sprite_##sprite_name##_animations, sprite_##sprite_name##_frame_data }

#define SET_ANIMATION_NAME(sprite_name, animation_name, index) \
  enum { sprite_##sprite_name##_##animation_name = index }


data.h
Code:
#ifndef _DATA_H
#define _DATA_H

#include "actor.h"
#include "sprite.h"

// =====================================
// *** SPRITES ***
// =====================================

// Player Sprite
DECLARE_SPRITE(player, 4, 6 + 3 + 1 + 6);
SET_ANIMATION_NAME(player, idle, 0);
SET_ANIMATION_NAME(player, walk, 1);
SET_ANIMATION_NAME(player, duck, 2);
SET_ANIMATION_NAME(player, dead, 3);

...


data.c
Code:
#include "data.h"


/* * * * * * * * * * * * * * * * * * * * * * * * * * *
typedef struct Sprite {
  void *info;
  void *data;
} Sprite;
* * * * * * * * * * * * * * * * * * * * * * * * * * */


// Player Sprite
// - - - - - - - - - - - - - - - - - - - - - - - - - -

#define _SPRITE_INFO { \
  {6, 0, 0,}, {3, 6, 0}, {1, 9, 0}, {6, 10, 1} \
}
#define _SPRITE_DATA { \
  {0xb5, 240}, {0xb6,   4}, {0xb7,   4}, \
  {0xb8, 120}, {0xb9,   4}, {0xb4,   6}, \
                                         \
  {0xb1,   3}, {0xb2,   3}, {0xb3,   3}, \
                                         \
  {0xba,   1},                           \
                                         \
  {0xc0,   2}, {0xc1,   2}, {0xc2,   2}, \
  {0xc3,   2}, {0xc4,   2}, {0xc5,   2}  \
}
CREATE_SPRITE(player, _SPRITE_INFO, _SPRITE_DATA);
#undef _SPRITE_DATA
#undef _SPRITE_INFO

...

_________________
Image


Top
 Profile  
 
PostPosted: Thu Nov 14, 2019 7:13 pm 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1908
wonder wrote:
I'm a little bit confused by your post, but isn't this enough?

Code:
#define DECLARE_NUMBER_WITH_POSTFIX(postfix) \
    int Number##postfix

DECLARE_NUMBER_WITH_POSTFIX(A);

The idea is that you don't simply write the postfix, but that the postfix is the value inside another macro.

This is what I want:
Code:
#define DECLARE_NUMBER_WITH_POSTFIX() \
    int Number##CurrentPostfix

#define CurrentPostfix A

DECLARE_NUMBER_WITH_POSTFIX();

And the number shall be called NumberA, not NumberCurrentPostfix.

Until now, the only way that I found to do this is like this:
Code:
#define DECLARE_NUMBER_WITH_POSTFIX__(postfix) \
    int Number##postfix

#define DECLARE_NUMBER_WITH_POSTFIX_(postfix) \
    DECLARE_NUMBER_WITH_POSTFIX__(postfix)

#define DECLARE_NUMBER_WITH_POSTFIX() \
    DECLARE_NUMBER_WITH_POSTFIX_(CurrentPostfix)

#define CurrentPostfix A

DECLARE_NUMBER_WITH_POSTFIX();

But I'm looking for somthing where I don't have to declare three macros every time.

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
PostPosted: Thu Nov 14, 2019 7:27 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 7634
Location: Canada
Trying to use C macros that interact with each other, or recursively, can be a bit tricky. The order in which they apply is not always very intuitive. cc65's preprocessor isn't really documented, though I think it's a fairly "normal" C preprocessor implementation. GCC has macro documentation but it's really hard to read. Wikipedia strangely has a concise description of this topic that might help a little.

If you want some insight as to how the preprocessor works, you can investigate the result of the preprocessor with the -E flag. Something like this will output a file that has had all the macro preprocessing applied:
Code:
cc65 -E -o thing.pre thing.c


Otherwise I can't offer much advice on the situation you asked about. To me it looks like it would take more time to understand than it would to find a different way to accomplish the same thing.


Top
 Profile  
 
PostPosted: Fri Nov 15, 2019 1:05 am 
Offline
User avatar

Joined: Sat Aug 31, 2019 2:12 pm
Posts: 23
rainwarrior wrote:
If you want some insight as to how the preprocessor works, you can investigate the result of the preprocessor with the -E flag. Something like this will output a file that has had all the macro preprocessing applied:
Code:
cc65 -E -o thing.pre thing.c


Exactly! :)
Furthermore, you can try the pre-processor live on this website: https://godbolt.org/ (lang: C, compiler: CC65, args: -E)
For your convenience, here's the direct link generated with the Share button: https://godbolt.org/z/3qXXQY

Removing the -E argument lets you see the generated assembly code in real time. Very useful for prototyping! :)

_________________
Image


Top
 Profile  
 
PostPosted: Sun Nov 17, 2019 4:20 am 
Offline
User avatar

Joined: Sat Sep 07, 2013 2:59 pm
Posts: 1908
Thanks for your information.

I did it like this now:
Code:
#define DefNameX_(name1, name2, name3, name4, name5, name6)\
   name1##name2##name3##name4##name5##name6

#define DefName6(name1, name2, name3, name4, name5, name6)\
   DefNameX_(name1, name2, name3, name4, name5, name6)

...

#define DefName2(name1, name2)\
   DefNameX_(name1, name2, , , , )

This way, I can do this:
Code:
#define DECLARE_NUMBER_WITH_POSTFIX()\
    int DefName2(Number, CurrentPostfix)

#define CurrentPostfix A

DECLARE_NUMBER_WITH_POSTFIX();
/* --> Generates int NumberA; */

And it has enough overloaded versions for all kinds of complicated names, for example:
CurrentArea##name##_b##whatBankType##CurrentBankNumber

_________________
Available now: My game "City Trouble".
Website: https://megacatstudios.com/products/city-trouble
Trailer: https://youtu.be/IYXpP59qSxA
Gameplay: https://youtu.be/Eee0yurkIW4
German Retro Gamer article: http://i67.tinypic.com/345o108.jpg


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Google [Bot], Google Adsense [Bot] and 8 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group