How are arguments in C/C++ macros handled implicitly? - macros

I'm trying to read and understand a file written in C (here) and not knowing much C (or if it's C++ to begin with), I'm wondering how the following:
#define BEGIN yy_start = 1 + 2 *
when called like this:
BEGIN(new_state)
is working. I know BEGIN is a macro/placeholder setting yy_start. However I can't find anything on how the argument passed in is handled and operands don't get me anywhere.
Question: How are arguments handled in a C/C++ macro if they are not handled explicitly?

How are arguments handled in a C/C++ macro if they are not handled explicitly?
If a macro is not declared with arguments then it does not take arguments at all. Indeed, C explicitly distinguishes between macros that accept arguments and those that don't. In your particular case, given a definition of BEGIN as an object-like macro:
#define BEGIN yy_start = 1 + 2 *
This invocation ...
BEGIN(new_state)
... expands to:
yy_start = 1 + 2 *(new_state)
. In particular, note that only the macro name is replaced. The parenthesized tokens following it are not part of the macro invocation, and are not affected by the macro expansion.

The macro BEGIN has no arguments so the resulting code will be
yy_start = 1 + 2 *(new_state)
It is done in preprocessing.

Related

How do I write a perl6 macro to enquote text?

I'm looking to create a macro in P6 which converts its argument to a string.
Here's my macro:
macro tfilter($expr) {
quasi {
my $str = Q ({{{$expr}}});
filter-sub $str;
};
}
And here is how I call it:
my #some = tfilter(age < 50);
However, when I run the program, I obtain the error:
Unable to parse expression in quote words; couldn't find final '>'
How do I fix this?
Your use case, converting some code to a string via a macro, is very reasonable. There isn't an established API for this yet (even in my head), although I have come across and thought about the same use case. It would be nice in cases such as:
assert a ** 2 + b ** 2 == c ** 2;
This assert statement macro could evaluate its expression, and if it fails, it could print it out. Printing it out requires stringifying it. (In fact, in this case, having file-and-line information would be a nice touch also.)
(Edit: 007 is a language laboratory to flesh out macros in Perl 6.)
Right now in 007 if you stringify a Q object (an AST), you get a condensed object representation of the AST itself, not the code it represents:
$ bin/007 -e='say(~quasi { 2 + 2 })'
Q::Infix::Addition {
identifier: Q::Identifier "infix:+",
lhs: Q::Literal::Int 2,
rhs: Q::Literal::Int 2
}
This is potentially more meaningful and immediate than outputting source code. Consider also the fact that it's possible to build ASTs that were never source code in the first place. (And people are expected to do this. And to mix such "synthetic Qtrees" with natural ones from programs.)
So maybe what we're looking at is a property on Q nodes called .source or something. Then we'd be able to do this:
$ bin/007 -e='say((quasi { 2 + 2 }).source)'
2 + 2
(Note: doesn't work yet.)
It's an interesting question what .source ought to output for synthetic Qtrees. Should it throw an exception? Or just output <black box source>? Or do a best-effort attempt to turn itself into stringified source?
Coming back to your original code, this line fascinates me:
my $str = Q ({{{$expr}}});
It's actually a really cogent attempt to express what you want to do (turn an AST into its string representation). But I doubt it'll ever work as-is. In the end, it's still kind of based on a source-code-as-strings kind of thinking à la C. The fundamental issue with it is that the place where you put your {{{$expr}}} (inside of a string quote environment) is not a place where an expression AST is able to go. From an AST node type perspective, it doesn't typecheck because expressions are not a subtype of quote environments.
Hope that helps!
(PS: Taking a step back, I think you're doing yourself a disservice by making filter-sub accept a string argument. What will you do with the string inside of this function? Parse it for information? In that case you'd be better off analyzing the AST, not the string.)
(PPS: Moritz++ on #perl6 points out that there's an unrelated syntax error in age < 50 that needs to be addressed. Perl 6 is picky about things being defined before they are used; macros do not change this equation much. Therefore, the Perl 6 parser is going to assume that age is a function you haven't declared yet. Then it's going to consider the < an opening quote character. Eventually it'll be disappointed that there's no >. Again, macros don't rescue you from needing to declare your variables up-front. (Though see #159 for further discussion.))

Julia: How to create a symbol inside a function that matches the input variable?

I have a Julia function that takes a few input arguments and uses them to perform multiple operations. In order to get one of those operations to work properly I need to be able to compute a symbol that matches the user input. For example the function looks something like this:
function func(arg1,arg2)
symb_arg1 = ## get the symbol for input into arg1
symb_arg2 = ## get the symbol for input into arg2
println(symb_arg1)
println(symb_arg2)
## Do some operations using arg1, arg2, symb_arg1, symb_arg1
end
I am hoping to achieve the following behavior:
a = 25
b = rand(27,55,18)
func(a,b) ## prints :a and :b
The difficulty here is to get the function to compute a symbol containing the actual name of the variable, rather than the value of the variable. This post provides the following macro that almost does what I want:
macro mymacro(ex)
Expr(:quote,ex) # this creates an expression that looks like :(:(x + 2))
end
This macro works well for doing the following:
a = rand(27,15)
symb_a = #mymacro(a) ## prints :a
However, using this macro inside my function will not produce the desired effect. Specifically, if I define my function as:
function func_bad(arg1,arg2)
symb_arg1 = #mymacro(arg1)
symb_arg2 = #mymacto(arg2)
println(symb_arg1)
println(symb_arg2)
## Do some operations using arg1, arg2, symb_arg1, symb_arg1
end
And then run the commands:
a = 25
b = rand(27,55,18)
func_bad(a,b) ## prints :arg1 and :arg2 (instead of the desired :a and :b)
Of course, one simple (but not so elegant) solution is to add additional input arguments for the function so that the user is responsible for creating the symbols. However this is more of a last resort. I would prefer the function be able to automatically create the symbols. Any idea as to how I can modify my function or the macro to achieve this behavior?
The simple answer is that this is not possible; there is an abstraction barrier that prevents functions from seeing implementation details of their callers. All they get is the values, which is a crucial property for robust and clear programs.
One thing you could do is write a macro to transform the call site:
#with_syms func(a, b)
into something like
func((:a,a), (:b,b))
passing symbol-value pairs into the function.
Another slightly different design would be to provide macro wrappers for all functions that need this behavior, so that calls would look like #func(a,b). You could factor out the argument list transformation to a helper function; each macro would look like
macro func(args...)
:(func($(pair_with_symbols(args)...)))
end

Does TASM allow a macro to be used as an operand?

I am attempting to port a macro from MASM6 to TASM5 (in IDEAL mode) and I am encountering errors. The macro itself assembles fine, but when I attempt to call it, I receive the following error during assembly:
Error xxx.asm(##) Can't use macro name in expression: M_SWAP16
The macro takes the numeric value from a text macro and performs a byte swap. The macro is generally called with ops that take immediate values or during variable initialization.
MACRO M_swap16 operand
LOCAL result
result = (((operand and 0FFh) shl 8) or ((operand and 0FF00h) shr 8))
exitm %result
ENDM
IPPROTO_TCP EQU 6
.
.
.
mov [protocol], M_swap16(IPPROTO_TCP) ; fails
.
.
.
protocol DW ?
protocol_default DW M_swap16(IPPROTO_TCP) ; fails
It works fine in MASM 6.11. Switching TASM from IDEAL to MASM mode doesn't help. Neither does moving the macro into the EQU statement. Ideas?
Unfortunately TASM5 doesn't appear to support macros returning results to expressions at least according to the last official docs. This is also what the error you are seeing is saying. More specifically, the EXITM directive doesn't take an argument like MASM can regardless of the mode you are in. However TASM's macros can still emit a line of code, so if you aren't worried about passing the expression in to the macro, I propose the following workaround (IDEAL mode):
MACRO M_swap16_EXPRESSION expr,operand
LOCAL result
result = (((operand and 0FFh) shl 8) or ((operand and 0FF00h) shr 8))
expr result
ENDM
The macro above takes an additional argument "expr" as the 1st argument which is the assembly expression you were trying to plug the original expression in. It will perform the assembly-time arithmetic on the operand and emit the final assembly line. It can be used like this:
M_swap16_EXPRESSION <mov [protocol],>,IPPROTO_TCP
...
M_swap16_EXPRESSION <protocol_default DW>,IPPROTO_TCP
I admit its ugly, but it might be the next best thing if you must use TASM.

Why is this macro replaced as 20 instead 10?

1. #define NUM 10
2. #define FOO NUM
3. #undef NUM
4. #define NUM 20
5.
6. FOO
When I only run the preprocessor, the output file contains 20.
However, from what I understand, the preprocessor simply does text replacement. So this is what I think is happening (which is obviously wrong but idky):
NUM is defined as 10.
Therefore, in line 2, NUM is replaced as 10. So now we have "#define FOO 10".
NUM is undefined.
NUM is redefined and now is 20.
FOO is replaced according to line 2, which was before line 4's redefinition, and is 10.
So I think the output should be 10 instead of 20. Can anything explain where it went wrong?
The text replacement is done where the macro is used, not where you wrote the #define. At the point you use FOO, it replaces FOO with NUM and NUM is currently defined to be 20.
In the interests of collecting all the relevant specifications from the standards, I extracted this information from a comment thread, and added C++ section numbers, based on draft N4527 (the normative text is identical in the two standards). The standard(s) are absolutely clear on the subject.
#define preprocessor directives do not undergo macro replacement.
(C11 §6.10¶7; C++ §16[cpp] ¶6): The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.
After a macro is replaced with its replacement text, the new text is rescanned. Preprocessor tokens in the replacement are expanded as macros if there is an active macro definition for the token at that point in the program.
(C11 §6.10.3¶9; C++ §16.3[cpp.replace] ¶9) A preprocessing directive of the form
# define identifier replacement-list new-line
defines an object-like macro that causes each subsequent instance of the macro name to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.
A macro definition is active from the line following the #define until an #undef for the macro name, or the end of the file.
(C11 §6.10.3.5¶1; C++ §16.3.5[cpp.scope] ¶1) A macro definition lasts (independent of block structure) until a corresponding #undef directive is encountered or (if none is encountered) until the end of the preprocessing translation unit. Macro definitions have no significance after translation phase 4.
If we look at the program:
#define NUM 10
#define FOO NUM
#undef NUM
#define NUM 20
FOO
we see that the macro definition of NUM in line 1 lasts exactly to line 3. There is no replaceable text in those lines, so the definition is never used; consequently, the program is effectively the same as:
#define FOO NUM
#define NUM 20
FOO
In this program, at the third line, there is an active definition for FOO, with replacement list NUM, and for NUM, with replacement list 20. The FOO is replaced with its replacement list, making it NUM, and then that is once again scanned for macros, resulting in NUM being replaced with its replacement list 20. That replacement is again rescanned, but there are no defined macros, so the end result is that the token 20 is left for processing in translation phase 5.
In:
FOO
the preprocessor will replace it with NUM, then it will replace NUM with what it is currently defined as, which is 20.
Those initial four lines are equivalent to:
#define FOO NUM
#define NUM 20
The C11 standard says (and other versions of C, and C++, say similarly):
A preprocessing directive of the form # define identifier replacement-list new-line defines an object-like macro that causes each subsequent instance of the macro name to be replaced by the replacement list of preprocessing tokens that constitute the remainder of the directive. The replacement list is then rescanned for more macro names as specified below.
However it also says in another part (thanks to rici for pointing this out).
The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.
So a subsequent instance of the macro name which is found inside another #define directive is actually not replaced.
Your line #define FOO NUM defines that when the token FOO is later found (outside of another #define directive!), it will be replaced by the token NUM .
After a token is replaced, rescanning occurs, and if NUM is itself a macro, then NUM is replaced at that point. (And if whatever NUM expands to contains macros , then that gets expanded , and so on).
So your sequence of steps is actually:
NUM defined as 10
FOO defined as NUM
NUM undefined and re-defined as 20
FOO expands to NUM
(rescan) NUM expands to 20
This behaviour can be seen in another common preprocessor trick, to turn the defined value of a macro into a string:
#define STR(X) #X
#define STR_MACRO(X) STR(X)
#define NUM 10
puts( STR_MACRO(NUM) ); // output: 10
If we had written puts( STR(NUM) ) then the output would be NUM.
The output of 10 is possible because, as before, the second #define here does not actually expand out STR. So the sequence of steps in this code is:
STR(X) defined as #X
STR_MACRO(X) defined as STR(X)
NUM defined as 10
STR_MACRO and NUM are both expanded; the result is puts( STR(10) );
(Rescan result of last expansion) STR(10) is expanded to "10"
(Rescan result of last expansion) No further expansion possible.

Fortran substitute subroutine name using macro

I am writing a module that allows users to log information. I want to provide an interface that logs a string message, which can be called as
call m_log(msg)
So in file m_logger.f90, I will have
module m_logger
..
subroutine m_log(msg)
..
end module
In file main.f90, a user will have
program main
use m_logger
call m_log(msg)
end program
Now how can I substitute call m_log(msg) with call m_log(msg, __FILE__, __LINE__) ?
Because of this substitution, a different subroutine subroutine m_log(msg, filename, linenum) in the logger module will be called instead.
If I use a macro like #define m_log(msg) m_log(msg,__FILE__,__LINE__) , it will have to be added to every user file that uses the logger.
Also, I do not want to enforce the user to pass __FILE__ and __LINE__ explicitly.
Is there a way I can do this? Or are there any other alternatives altogether?
Thanks in advance
Edit:
I had a discussion on comp.lang.fortran. Adding a link for reference.
here
In this case you would have to use the same approach C uses. Define the macro you proposed
#define log(msg) m_log(msg,__FILE__,__LINE__)
in a separate file (possibly with other useful macros) and include it using #include "file.inc" (standard Fortran include won't suffice).
If the macro has a different name, than the subroutine it actually calls, you can ensure that the user has to use the include and cannot forget it.
If you don't want to force __file__ and __line__ explicitly, then you can use the optional flag, such that your subroutine looks like:
subroutine m_log(msg, filename, linenum)
character(len=*) :: msg
character(len=*), optional :: filename
integer, optional :: linenum
if(present(filename)) then
<something with filename>
endif
if(present(linenum)) then
<something with linenume>
endif
<normal stuff with msg>
end subroutine
The intrinsic function present returns a true value if filename or linenum have any values attached to it, returning false otherwise.
Since you want them to be passed as compiler macros by the user, you would first have to choose different names for your macros. __FILE__ and __LINE__ are both predefined macros. These two macros are defined by preprocessor, not passed by the user. I think that might have cause some confusion.
If you would like to allow users to optionally supply the macros through compiler options, it is probably best to include #ifdef directive in your subroutine:
subroutine m_log(msg)
implicit none
character(len=*) :: msg
character(len=something) :: file
integer ::line
!Initialize file and line to some default value
file=...
line=...
#ifdef __KVM_FILE__
file=__KVM_FILE__
#endif
#ifdef __KVM_LINE__
line=__KVM_LINE__
#endif
...
This way the user will always call the subroutine with the same syntax call m_log(something), but the effect will change according to your compilation macros. Of course, that would also require the user to recompile your code every time they change this macro. If this is too costly to do, you can set up a subroutine with optional argument (as in Kyle's answer), then enclose #define macro in #ifdef blocks, and put them into an .h file, and have your user always include that file. (similar to Vladimir's answer)