* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This source file is part of SableVM. * * * * See the file "LICENSE" for the copyright information and for * * the terms and conditions for copying, distribution and * * modification of this source file. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * m4 macros in SableVM ==================== SableVM provides a set of powerful m4 macros. This document describes their usage, problems that may occur, and walks through the complexities of instructions_preparation.m4.c. More documentation can be found in ./src/libsablevm/macros.m4 Mixed C and m4 files ==================== Oftentimes it may be convenient to have m4 macros inside certain portions of a C file. Here is an easy way to convert from .c/.h to .m4.c/.m4.h If you change a file like this, you need to change Makefile.am to build it properly. This is relatively easy, and there are many examples to follow. You should also use 'svn mv .c .m4.c' so that the file keeps sandbox history. Then, make sure the file follows this format, defining macros wherever you need them: /* m4svm_file_name */ <---- 1st line of file /* m4svm_on(0)m4_dnl */ << ordinary C code >> /* some comment *[::]/ m4svm_off (); */ m4svm_define_begin v = ":], [:m4svm_macro_name:])"; << C macro body here >> m4svm_define_end v = ":])"; /* m4svm_macro_name(arg1,arg2,...,argN) m4_undefine([:m4svm_macro_name:]) m4svm_on(0)m4_dnl */ << more ordinary C code >> EOF C comments with commas inside macro bodies ========================================== If you have C comments in a macro body, you cannot put a `,' inside them. Rather, you must quote them using the redefined quote tokens, like so: [:,:] Usually it's easier just to write the C comments without commas in the first place. Mismatched C parentheses in a macro body ======================================== If for some reason you have mismatched parentheses in a macro body, this will confuse m4 even if the mismatch is only relevant to the generated C code. You might think it is an m4 bug when really it's the C code that's at fault. Maximum macro body length ========================= At some point, while writing a long instruction in instructions.m4.c, I came across a maximum where m4 would no longer recognize the m4svm_instruction_tail() macro properly. If you have really long macro bodies (500+ lines), and are getting confusing m4 errors, try cutting down the size of the macro body. Details on instructions_preparation.m4.c ======================================== Here we'll cover m4svm_instruction_1, m4svm_instruction_2$1, and the rest of the stuff in ./src/libsablevm/instructions_preparation.m4.c The problem is that GNU indent puts a space between the function and the left parenthesis, e.g. 'foo (arg1, arg2);'. Unfortunately m4 does not allow for a space between the parenthesis and the macro name. So, we have to play tricks. :-) Let's do it in steps. STEP 1. m4svm_instruction_head (NOP, SVM_INTRP_FLAG_INLINEABLE, 0); expands to: m4svm_instruction_1( (NOP, SVM_INTRP_FLAG_INLINEABLE, 0); << instruction body in C >> m4svm_instruction_tail (); Now, m4svm_instruction_tail expands to: ))m4_dnl (); This whole thing (after applying m4_dnl) becomes: m4svm_instruction_1( (NOP, SVM_INTRP_FLAG_INLINEABLE, 0); << instruction body in C >> )) STEP 2. The above result becomes a call to m4svm_instruction_1 with a single parameter [delimited by parentheses]. The argument is: (NOP, SVM_INTRP_FLAG_INLINEABLE, 0); << instruction body in C >> ) STEP 3. m4svm_instruction_1 is expanded and we get: m4svm_instruction_2(NOP, SVM_INTRP_FLAG_INLINEABLE, 0); Which ends with a ";", and it does not include the instruction body. So, we must expand m4svm_instruction_2. STEP 4. m4svm_instruction_2(NOP, SVM_INTRP_FLAG_INLINEABLE, 0); expands to: m4svm_instruction($1, $2, $3,m4_dnl or, more precisely: m4svm_instruction(NOP, SVM_INTRP_FLAG_INLINEABLE, 0,m4_dnl; So, after applying m4_dnl, the whole thing now looks as: m4svm_instruction(NOP, SVM_INTRP_FLAG_INLINEABLE, 0, << instruction body in C >> ) Which also gets rid of the ";" at the end of the m4svm_instruction_head line. Now m4svm_instruction has all the params that we wanted it to have.