Help Me Understand this Code

Hi,

I'm working on a project involving an Eink display and have to make some modifications. I'm very new to arduino coding, and can't really follow a certain part of the code. I'll paste it here:

define IMAGE_1 cat

define IMAGE_2 dog

define IMAGE_3 apple

define MAKE_STRING1(X) #X

define MAKE_STRING(X) MAKE_STRING1(X)

define ID(X) X

define MAKE_NAME1(X,Y) ID(X##Y)

define MAKE_NAME(X,Y) MAKE_NAME1(X,Y)

define MAKE_JOIN(X,Y) MAKE_STRING(MAKE_NAME(X,Y))

define IMAGE_1_FILE MAKE_JOIN(IMAGE_1,EPD_IMAGE_FILE_SUFFIX)

define IMAGE_1_BITS MAKE_NAME(IMAGE_1,EPD_IMAGE_NAME_SUFFIX)

define IMAGE_2_FILE MAKE_JOIN(IMAGE_2,EPD_IMAGE_FILE_SUFFIX)

define IMAGE_2_BITS MAKE_NAME(IMAGE_2,EPD_IMAGE_NAME_SUFFIX)

define IMAGE_3_FILE MAKE_JOIN(IMAGE_3,EPD_IMAGE_FILE_SUFFIX)

define IMAGE_3_BITS MAKE_NAME(IMAGE_3,EPD_IMAGE_NAME_SUFFIX)

Later on in the code, IMAGE_1_BITS, and the others, are used in a switch to display the images. Can anyone guide me as to what is happening here?

This is basically the demo code that was included in the tutorial. I can add more images if I just followed the syntax but because of our needs, we need to alternate between a hundred or so mages. So declaring all of them, and making a switch with a hundred cases doesn't look like the right way to go.

If anyone has any ideas I would be so greatful. Thanks!

https://gcc.gnu.org/onlinedocs/cpp/Stringification.html

What is the output format of MAKE_NAME? When I print them, MAKE_JOIN outputs a string but MAKE_NAME gives me an error.

What I’d also like to know is is there another way to implement what is going on here in a completely different way? The way this code is made, each image is defined and has several lines of code. If there were only a few images, that would be fine, but what we are to do is to alternate between hundreds of images with a fixed delay, and defining each of those images doesn’t seem to be the best idea.

If anyone would like to check the current code and help me out that would be great! I attached the code we have so far.

Eink_test.c (4.7 KB)

This isn't really code, rather macro instructions to the compiler. Have you read and understood the material in the link (reply #1)?

Of course there are alternative ways of entering file names into your code.

Yes I did. But unlike the example on the link where it is very simplistic and you can follow the flow, the code I'm working is confusing me, and I have to repeat that I don't have a lot of experience with this. First of:

define MAKE_STRING1(X) #X

define MAKE_STRING(X) MAKE_STRING1(X)

what is the reason why you would put MAKE_STRING1 as the input of MAKE_STRING? Doesn't MAKE_STRING1 already make whatever #X is a string?

also:

define MAKE_NAME(X,Y) MAKE_NAME1(X,Y)

define MAKE_JOIN(X,Y) MAKE_STRING(MAKE_NAME(X,Y))

MAKE_JOIN I believe goes back to MAKE_STRING1 and it has the leading # so I guess that makes the output a string, while MAKE_NAME goes back to ID, which doesn't have the leading # so what does that make its output?

I have a lot more questions... Honestly, this is all so confusing.

Yes, this is just part of the code, the rest I didn't include since I understand the lower part and how the result of these macros are used. I just don't get how they came to be. I attached the entire code on my previous post.

what is the reason why you would put MAKE_STRING1 as the input of MAKE_STRING? Doesn’t MAKE_STRING1 already make whatever #X is a string?

This process is explained in the link provided in reply #1 (only the names have been changed):

If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.

#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> “foo”
xstr (foo)
==> xstr (4)
==> str (4)
==> “4”

s is stringified when it is used in str, so it is not macro-expanded first. But s is an ordinary argument to xstr, so it is completely macro-expanded before xstr itself is expanded (see Argument Prescan). Therefore, by the time str gets to its argument, it has already been macro-expanded.

All this does is create file names for #include and variable names to use as function call arguments. If you have hundreds of these, you need to come up with a better approach.

I've been reviewing the same code and have some further explanation for any future readers of this page.

The reason to use multiple macros with similar names is to be able to pass macros in as macro arguments and have them get expanded. This is what is explained by the stringification reference and jremington. This same logic holds true for the MAKE_JOIN/MAKE_NAME example. If we look at the MAKE_JOIN macro:

#define MAKE_JOIN(X,Y) MAKE_STRING(MAKE_NAME(X,Y))

We see that the arguments (X,Y) are passed to MAKE_NAME. Looking at the MAKE_NAME macro:

#define MAKE_NAME(X,Y) MAKE_NAME1(X,Y)

Here X and Y are macro expanded and then passed to MAKE_NAME1. Looking at MAKE_NAME1:

#define MAKE_NAME1(X,Y) ID(X##Y)

If we had omitted the original call to MAKE_NAME and had MAKE_JOIN directly call MAKE_NAME1 then X and Y would have never been macro expanded since stringified and concatenated (this is the ## operator between X and Y) macro arguments are not macro expanded as according to the references.