"Sputnik" help  
Sputnik Help
Language Reference - Preprocessor - Stringification


Sometimes you may want to convert a macro argument into a string constant. Parameters are not replaced inside string constants, but you can use the ‘#’ preprocessing operator instead. When a macro parameter is used with a leading ‘#’, the preprocessor replaces it with the literal text of the actual argument, converted to a string constant. Unlike normal parameter replacement, the argument is not macro-expanded first. This is called stringification.

There is no way to combine an argument with surrounding text and stringify it all together. Instead, you can write a series of adjacent string constants and stringified arguments. The preprocessor will replace the stringified arguments with string constants.

#define WARN_IF(EXP) \
                do \
                { \
                    if (EXP) \
                        printf("Warning: " #EXP "\n"); \
                } \
my $a = 0;
WARN_IF ($x == 0);
//do { if ($x == 0) printf("Warning: \$x == 0\n"); } while (0)

// Warning: $x == 0

The argument for EXP is substituted once, as-is, into the if statement, and once, stringified, into the argument to printf. If x were a macro, it would be expanded in the if statement, but not in the string.

The do and while (0) are a kludge to make it possible to write WARN_IF (arg);, which the resemblance of WARN_IF to a function would make Sputnik programmers want to do; see Swallowing the Semicolon.

Stringification in Sputnik involves more than putting double-quote characters around the fragment. The preprocessor backslash-escapes the quotes surrounding embedded string constants, and all backslashes within string and character constants, in order to get a valid Sputnik string constant with the proper contents. Thus, stringifying $p = "foo\n"; results in "$p = \"foo\\n\";". However, backslashes that are not inside string or character constants are not duplicated: ‘\n’ by itself stringifies to "\n".

All leading and trailing whitespace in text being stringified is ignored. Any sequence of whitespace in the middle of the text is converted to a single space in the stringified result.
Comments are replaced by whitespace long before stringification happens, so they never appear in stringified text.
There is no way to convert a macro argument into a character constant. If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.

#define XSTR(s) STR(s)
#define STR(s) #s
#define FOO 4
say STR(FOO); // "foo"
say XSTR(FOO); // xstr (4)
               // str (4)
               // "4"
// FOO
// 4

s is stringified when it is used in STR, so it is not macro-expanded first. But s is an ordinary argument to XSTR, so it is completely macro-expanded before XSTR itself is expanded Argument Prescan. Therefore, by the time STR gets to its argument, it has already been macro-expanded.

It is possible to call the Sputnik Interperator during a macro to execute functions such as changing a strings case like this:

#define UC(x)  %(uc(x))
#define STR(...) #__VaArgs__
#define USTR(...)  UC(#__VaArgs__)

say STR(mov eax, esi);
say USTR(mov eax, esi);

// mov eax, esi

So here we defined a USTR macro to make a string uppercase then we call the UC macro which runs the Sputnik Interperator to execute the string uppercasing.

This is a very powerful feature since it lets you run any Sputnik code inside your macro.


Cheryl (uberfox@hotmail.com)