GNU assembler: creating a symbol using macro argument - macros

I have a macro which creates labels, but I only want to create those labels if they aren't already defined. The problem is that the label is built using a macro argument, and the assembler doesn't like symbols generated using macro arguments. This is the code that doesn't work. It errors out on the ifndef. Is there any other way to write this?
.macro create_handler modifier
.ifndef handler\modifier
handler\modifier:
some code
some more code
.endif
.endif
Error: junk at end of line, first unrecognized character is `\'

I think there are two problems. One is that \modifier: looks for a macro argument named modifier:, with the colon. You need to use \modifier\(): instead. \() breaks up the string so the parser knows that you have just ended the name of the argument.
Second, the last .endif should be a .endm:
.macro create_handler modifier
.ifndef handler\modifier
handler\modifier\():
.4byte 0
.endif
.endm
create_handler foo
create_handler foo
This results in this listing (ignore the line numbers, I added this to one of my existing files):
74 0010 00000000 create_handler foo
75 create_handler foo
DEFINED SYMBOLS
../src/core_dict.S:74 .text:00000010 handlerfoo
As you can see, only one handlerfoo was created.

Related

implicit __source__ argument to julia macro can't be used within quote block

I'll start with my code:
macro example(args...)
local s = __source__
println(s) # This part works, showing macro is called on line 9
quote
println(s) # Julia tells me this variable "s" is not defined
println(__source__) # Likewise, "__source__" is not defined here either
end
end
#example 42 # Line 9 of my file
In my macro above I want to record the line number that is calling the macro and use it within my quote block. Both capturing it in a variable outside the quote block and using it within, or using it directly in the quote block don't work. My understanding is the code outside the quote block runs at parse-time, and the expression returned from the quote block is evaluated at run-time.
I feel like there must be a way to capture that variable and inject it right into the expression that will be evaluated later, but I haven't figured out how to do that. Any help here is appreciated. If there is a better way to do this let me know.
I ended up finding out an answer on my own. In the second line if I changed __source__ to __source__.line or __source__.file it worked fine as long as I then used $ to interpolate the result into the expression the macro returned. I'm still not sure why __source__ on its own didn't work, but using either .line or .file methods is working for me now.
I'm experiencing a similar problem trying to use __source__.
I think I can offer insight into why source.line, etc worked though.
The value of source.line is an integer. The value of source.fike is a string. Numbers and strings evaluate to themselves.
A symbol, on the other hand, evaluates to whatever value it has in the environment.

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.

SPSS Macro - Generate dynamic Varnames

I am currently trying to create dynamic variable names based on the valuelabels of the passed Argument. Currently, I have something like this:
COMPUTE counter = 0.
APPLY DICTIONARY FROM *
/SOURCE VARIABLES = V601
/TARGET VARIABLES = counter.
DEFINE !macro1 (!POS !CMDEND).
STRING name (A20).
!DO !#i = 1 !TO 62
COMPUTE counter = #i
!IF (!POS !EQ !i)
!THEN
COMPUTE name = VALUELABEL(!POS)
COMPUTE !CONCAT('wasnot', name) = 1.
!ELSE
COMPUTE name = VALUELABEL(!counter).
COMPUTE !CONCAT('wasnot', name) = 0.
!IFEND
!DOEND
CROSSTABS v15 by !CONCAT('wasnot', name) /cells = column.
!ENDDEFINE.
The idea is, that for every unique value of V601 a flag variable will be created (e.g. "wasnotvaluelabel1"). This variable will either have value = 1 or 0 respectively. However, it seems that concat cannot be used the way I intended. I get these errors:
Error # 6843 in column 7. Text: !POS
The end of a macro expression occurred when an operand was expected.
Execution of this command stops.
Error # 6846 in column 7. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6836 in column 12. Text: !EQ
In a macro expression, an operator was not preceded by an operand.
Error # 6846 in column 2. Text: !THEN
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Error # 6846 in column 28. Text: !POS
A macro expression includes an undefined macro variable or a macro operator
which is not valid within an expression.
Questions I have right now:
Is it even possible to generate dynamic names? I have tried
different attempts over the last hours but the SPSS macro "language"
seems very restricted.
Is there perhaps some other way to achieve this Task? It seems rather unconvenient.
Please note, working with the Python AddIn is sadly not an Option. I'm grateful for any received advice.
There is an extension command, SPSSINC CREATE DUMMIES, that will create all these dummy variables automatically. It's on the Transform menu. And it is implemented in Python.
Using Python you can easily read case data and do lots more.
Thanks for all the Help. In the end I did it with generating new syntax using Outfile.

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.

How to create a string from a pre-processor macro

I have a preprocessor macro that represents a hierarchical path into my design.
Example:
`define HPATH top.chip.block
I need to construct a string which holds the value of `HPATH, so in my example the string should equal top.chip.block.
Is there a way to construct such a string?
None of the following attempts worked:
string hpath;
hpath = "`HPATH"; // Results in hpath = "`HPATH"
hpath = \"``HPATH\"; // Doesn't compile
hpath = `HPATH; // Doesn't compile
I want hpath to be equivalent to doing this assignment hpath = "top.chip.block", but by using `HPATH instead of specifying the path again.
I cannot use %m because I need the string within my top-level UVM environment, not within a module.
A little more background: the reason I want to do this is because I am using backdoor register access in the UVM class library. The backdoor API requires setting the hdl_path to the blocks within the design, as a string. I already have `defines for the hierarchical paths and am trying to reuse those when specifying the hdl_paths so I don't have the same path defined twice. My testbench will use both the hierarchical path and the string path.
It's not possible to use a `define macro within a string literal. According to the SystemVerilog LRM:
Macro substitution and argument substitution shall not occur within string literals.
However a string literal can be constructed by using a macro that takes an argument and including the quotes in the macro by using ``"`.
Again, from the LRM:
An `" overrides the usual lexical meaning of " and indicates that the expansion shall include the quotation
mark, substitution of actual arguments, and expansions of embedded macros. This allows string literals to be
constructed from macro arguments.
So this works:
`define STRINGIFY(x) `"x`"
`define HPATH top.chip.block
string hpath = `STRINGIFY(`HPATH);
$display(hpath); // Output: "top.chip.block"
The example code can be run here: http://www.edaplayground.com/s/4/879
I know this is an old thread, but I thought I'd share our solution. The use of the $sformatf allows additional information to be added if needed.
`define STRINGIFY(DEFINE) $sformatf("%0s", `"DEFINE`")
I think this is what you're looking for.
`define HPATH `"top.chip.block`"
string hpath = `HPATH;
As toolic pointed out, the escape sequence %m will give you the current hierarchy when used in a $display statement so that may be a better option.