m4-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: File extensions to use pre-processing C source?


From: Daniel Goldman
Subject: Re: File extensions to use pre-processing C source?
Date: Fri, 25 Apr 2014 22:08:04 -0700
User-agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.3.0

On 4/23/2014 12:48 AM, Raphael 'kena' Poss wrote:
Dear Daniel,

here at UvA we have developed a C extension which requires m4 preprocessing, so 
I wanted to share the experience. Maybe you will find something for you there.

In our setting we use m4 *after* the C preprocessor.
So the chain is:

    .c -> (cpp) -> .i -> (m4) -> .i.c -> (gcc) -> .o

The reason is that we want to expand m4 macros in all headers imported from 
#include.
Also m4 macro uses may be generated as a result of expanding C macros.
To manage the compile chain of course you can write Makefiles, but for our 
application I found it easier to write a custom compiler driver that invokes 
the right tools depending on the type of files given on the command line.

Also any way you choose, you may want to care about line numbers. The format used by m4 
is slightly different from the one expected/used by gcc. Especially if you run cpp first, 
you want m4 to "know" about custom line number information. I made a patch to 
m4 in that direction, posted on the m4-patches mailing list in 2009/2010, but it has not 
been merged yet. Ping me if you are interested.

Best regards,



Hi Raphael,

I tried confirming what you said about getting m4 into the gcc
toolchain: first cpp, then m4, then gcc. It seems to work well, and keep
the .c / .h line numbers for error reporting straight. But maybe my test
cases are too limited. Is there another situation that messes up the
line numbers?

############

$ cat test-1.c
/* Has error - MESSAGE_2 not defined in .h file */
/* Has error - missing semicolon on line 10 */

#include <stdio.h>
#include "macros-1.h"
#include "globals-1.h"

int main () {
  printf (CPP_MESSAGE_1);
  printf (M4_MESSAGE_2);
  printf (CPP_MESSAGE_3)

  return 0;
  }

############

$ cat macros-1.h
/* one warning - redefines MESSAGE_3 on line 7 */

#define CPP_SOMETHING_ELSE ANOTHER_THING

#define CPP_MESSAGE_1 "Hello, world!\n"
#define CPP_MESSAGE_3 "Goodbye, world!\n"
#define CPP_MESSAGE_3 "I did it my way!\n"

############

$ cat globals-1.h
/* one error - omits semicolon on line 4 */

int Global_Array_1 [CPP_GLOBAL_ARRAY_1_LEN];
int Global_Array_2 [CPP_GLOBAL_ARRAY_2_LEN];
int Global_Array_3 [M4_GLOBAL_ARRAY_3_LEN];

int Global_Var_1;
int Global_Var_2
int Global_Var_3;

############

$ cat macros-1.m4
m4_dnl No errors in this file
m4_dnl If the .m4 file has errors, m4 will report directly

m4_define(M4_MESSAGE_1, "Hello, world!\n")
m4_define(M4_MESSAGE_2, "I did it m4 way!!\n")
m4_define(M4_MESSAGE_3, "Goodbye, world!\n")

m4_define(M4_GLOBAL_ARRAY_3_LEN, 99)

############

$ cat test-1.sh
function run_gcc_in_one_step {
  echo
  echo "//// Regular gcc compile: .c -> exefile"
  echo

  gcc test-1.c
  }

function run_gcc_in_two_steps {
  echo
  echo "//// Generate intermediate .i file: .c -> .i -> exefile"
  echo

  gcc -E test-1.c > test-1.i
  gcc test-1.i
  }

function run_m4_on_dot_i_file {
  echo
  echo "//// Run m4 on .i file: .c -> .i -> .m4.i -> exefile"
  echo

  gcc -E test-1.c > test-1.i
  m4 -P macros-1.m4 test-1.i > test-1.m4.i
  gcc test-1.m4.i
  }

run_gcc_in_one_step
run_gcc_in_two_steps
run_m4_on_dot_i_file

############

$ test-1.sh

//// Regular gcc compile: .c -> exefile

In file included from test-1.c:5:0:
macros-1.h:7:0: warning: "CPP_MESSAGE_3" redefined [enabled by default]
macros-1.h:6:0: note: this is the location of the previous definition
In file included from test-1.c:6:0:
globals-1.h:3:21: error: âCPP_GLOBAL_ARRAY_1_LENâ undeclared here (not
in a function)
globals-1.h:4:21: error: âCPP_GLOBAL_ARRAY_2_LENâ undeclared here (not
in a function)
globals-1.h:5:21: error: âM4_GLOBAL_ARRAY_3_LENâ undeclared here (not in
a function)
globals-1.h:9:1: error: expected â=â, â,â, â;â, âasmâ or â__attribute__â
before âintâ
test-1.c: In function âmainâ:
test-1.c:10:11: error: âM4_MESSAGE_2â undeclared (first use in this
function)
test-1.c:10:11: note: each undeclared identifier is reported only once
for each function it appears in
test-1.c:13:3: error: expected â;â before âreturnâ

//// Generate intermediate .i file: .c -> .i -> exefile

In file included from test-1.c:5:0:
macros-1.h:7:0: warning: "CPP_MESSAGE_3" redefined [enabled by default]
macros-1.h:6:0: note: this is the location of the previous definition
In file included from test-1.c:6:0:
globals-1.h:3:21: error: âCPP_GLOBAL_ARRAY_1_LENâ undeclared here (not
in a function)
globals-1.h:4:21: error: âCPP_GLOBAL_ARRAY_2_LENâ undeclared here (not
in a function)
globals-1.h:5:21: error: âM4_GLOBAL_ARRAY_3_LENâ undeclared here (not in
a function)
globals-1.h:9:1: error: expected â=â, â,â, â;â, âasmâ or â__attribute__â
before âintâ
test-1.c: In function âmainâ:
test-1.c:10:11: error: âM4_MESSAGE_2â undeclared (first use in this
function)
test-1.c:10:11: note: each undeclared identifier is reported only once
for each function it appears in
test-1.c:13:3: error: expected â;â before âreturnâ

//// Run m4 on .i file: .c -> .i -> .m4.i -> exefile

In file included from test-1.c:5:0:
macros-1.h:7:0: warning: "CPP_MESSAGE_3" redefined [enabled by default]
macros-1.h:6:0: note: this is the location of the previous definition
m4:macros-1.m4:4: Warning: excess arguments to builtin `m4_define' ignored
m4:macros-1.m4:6: Warning: excess arguments to builtin `m4_define' ignored
In file included from test-1.c:6:0:
globals-1.h:3:21: error: âCPP_GLOBAL_ARRAY_1_LENâ undeclared here (not
in a function)
globals-1.h:4:21: error: âCPP_GLOBAL_ARRAY_2_LENâ undeclared here (not
in a function)
globals-1.h:9:1: error: expected â=â, â,â, â;â, âasmâ or â__attribute__â
before âintâ
test-1.c: In function âmainâ:
test-1.c:13:3: error: expected â;â before âreturnâ

############

It looks like the way you suggest keeps all the .c / .h line numbers
straight when an error occurs, for the cases I dreamed up so far. The
only change I made was to use ".m4.i" suffix (instead of ".i.c").

I did not do these kinds of experiments on the alternative, where m4 is
run before cpp.

Can you (or anyone) explain why m4 has to "know" about cpp custom line
number information? Is that for cases where m4 expansion inserts extra
lines? If that is so, can you suggest a simple test case where m4
inserts extra lines into .c or .h file, or otherwise does something that
gets the numbering mixed up?

Thanks,
Daniel


reply via email to

[Prev in Thread] Current Thread [Next in Thread]