Fortran and cpp option : How to protect a comma?

Viewed 77

An option is defined (value = 1 or 2) to chose between two instructions and I would like to use with an instruction which have a comma.

#define option 1

#if option == 1
#define my_instr(instr1, instr2) instr1
#else if option == 2
#define my_instr(instr1, instr2) instr2
#endif

It works but when there is a comma in the instruction, I have a problem.

For example :

program main

 my_instr(print *,"opt 1", print * ,"opt 2")

end program main

does not compile (gftran -cpp) : Too much args. I am ok.

Thus, to escape the comma, parentheses are added : my_instr((print *,"opt 1"), (print * ,"opt 2"))

But it does not compile any more because of parentheses.

How can I solve that ?

2 Answers

Using the answer (https://stackoverflow.com/a/46311121/7462275), I found a " solution ".

#define option 2

#define unparen(...) __VA_ARGS__

#if option == 1
#define my_instr(instr1, instr2) unparen instr1
#elif option == 2
#define my_instr(instr1, instr2) unparen instr2
#endif

 program main
 
   my_instr((print *,"opt 1"), (print * ,"opt 2"))

 end program main

But,

  1. gfortran -cpp does not compile (problem with __VA_ARGS__). So, cpp -P is used before gfortran
  2. __VA_ARGS__ : It is not standard to use __VA_ARGS__ without something before (cf comments of :
    Matthew D. Scholefield in the answer used : Just something to note, this still doesn't conform to the C standard because of the use of a variadic macro.
    and KamilCuk in this question)
  3. Even instructions without comma need to be enclosed between parentheses

This will select the correct string.

#ifdef my_instr
#undef my_instr
#endif
#define my_instr(x) print *, x

#if option == 1
#define str "Opt 1"
#else if option == 2
#define str "Opt 2"
#endif

program foo
  my_instr(str)
end program foo

% gfortran -E -Doption=2 a.F90 | cat -s
# 1 "a.F90"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "a.F90"

program foo
  print *, "Opt 2"
end program foo

Related