m-schmoock / lcpp

A Lua C PreProcessor

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Macro evaluation order and application order must be opposite

Kerrigan29a opened this issue · comments

The order of application of the macros must be the opposite (I suppose). An example:

#define log(x) puts(x)
#define TOSTR(x) _TOSTR(x)
#define _TOSTR(x)  #x
int main(int argc, char const *argv[])
{
    printf("hi from line %u\n", __LINE__);
    log("hi from line " TOSTR(__LINE__));
    puts("hi from line " TOSTR(__LINE__));
    return 0;
}

If I precompile this code with Clang (also with gcc and cl.exe) I get:

#1 "test_short.c"
#1 "<built-in>" 1
#1 "<built-in>" 3
#170 "<built-in>" 3
#1 "<command line>" 1
#1 "<built-in>" 2
#1 "test_short.c" 2
int main(int argc, char const *argv[])
{
    printf("hi from line %u\n", 11);
    puts("hi from line " "12");
    puts("hi from line " "13");
    return 0;
}

In the puts line, Clan use this order to evaluate the macros:

  1. TOSTR
  2. _TOSTR
  3. #x
    4.__LINE__
    BUT applies the macros in the opposite order:
    1.__LINE__
    2.#x

But if I use lcpp:

../lua/src/lua -e 'lcpp = require("lcpp"); local out = lcpp.compileFile("test_short.c"); print(out);'

I get

int main(int argc, char const *argv[])
{
printf("hi from line %u\n", 10);
puts("hi from line ");
puts("hi from line __LINE__");
return 0;
}

Because the application goes in the same order of the evaluation:

  1. TOSTR
  2. _TOSTR
  3. #x
    So, the stringification is applied before the __LINE__ substitution and then __LINE__ is a string, not an identifier

Sorry for my english and thank you for your work.

hmm, I understand the problem, but its not so simple.
consider following example. it evaluate FUNC prior to __ARG.
we are now thinking good way to handle both.

BTW: please do not mind your english. I'm Japanese which has poor english skill :<
and your english is far more better than mine 👍

#include <stdio.h>
#include <stdlib.h>
#define FUNC__ARG 500
#define FUNC100 400
#define __ARG 100
#define FUNC(x) FUNC##x
int main(int argc, char *argv[]) {
    printf("%d\n", FUNC(__ARG)); //prints 500, not 400
}

hi, it should be fixed with umegaya/ffiex#20
I will backport this fix to lcpp after CI passed. thanks.

If I understand you correct, you say it must return 400 and not 500, but in fact the it must print 500 and not 400. Examples:

In Ubungu with gcc:

$ echo "#include <stdio.h>
#include <stdlib.h>
#define FUNC__ARG 500
#define FUNC100 400
#define __ARG 100
#define FUNC(x) FUNC##x
int main(int argc, char *argv[]) {
    printf("%d\n", FUNC(__ARG)); //prints 500, not 400
}" > test.c
$
$
$ gcc -E test.c | tail -n 3
int main(int argc, char *argv[]) {
    printf(%dn, 500);
}

In Mac with Clang:

$ echo "#include <stdio.h>
#include <stdlib.h>
#define FUNC__ARG 500
#define FUNC100 400
#define __ARG 100
#define FUNC(x) FUNC##x
int main(int argc, char *argv[]) {
    printf("%d\n", FUNC(__ARG)); //prints 500, not 400
}" > test.c
$
$
$ clang -E test.c | tail -n 3
int main(int argc, char *argv[]) {
    printf(%dn, 500);
}

In Windows with cl.exe

> notepad test.c
>
>
> cl.exe -E test.c
[...]

int main(int argc, char *argv[]) {
    printf("%d\n", 500);
}

If I understand you correct, you say it must return 400 and not 500

oh, that is misunderstanding :<
what I mean with this sample is,
"if evaluation order is same as the case of #x (stringify operator),
this program should print 400 but actually it prints 500, so evaluation order is different for both (# and ##) case"

and current lcpp is made for processing ## (concat operator) correctly, it causes problem that you report.

anyway, it has been fixed with
https://github.com/umegaya/ffiex/blob/master/ffiex/lcpp.lua (see here)
I will port the fix to this project in a while (sorry for my laziness)

"(sorry for my laziness)"
no problem, im also very lazy :D