Skip to main content

IAR Embedded Workbench for RISC-V 3.40

Reference information on the macro language

In this section:

Macro functions

C-SPY macro functions consist of C-SPY variable definitions and macro statements which are executed when the macro is called. An unlimited number of parameters can be passed to a macro function, and macro functions can return a value on exit.

A C-SPY macro has this form:

macroName (parameterList)
{
  macroBody
}

where parameterList is a list of macro parameters separated by commas, and macroBody is any series of C-SPY variable definitions and C-SPY statements.

Type checking is neither performed on the values passed to the macro functions nor on the return value.

Macro variables

A macro variable is a variable defined and allocated outside your application. It can then be used in a C-SPY expression, or you can assign application data—values of the variables in your application—to it. For more information about C-SPY expressions, see C-SPY expressions.

The syntax for defining one or more macro variables is:

__var nameList;

where nameList is a list of C-SPY variable names separated by commas.

A macro variable defined outside a macro body has global scope, and it exists throughout the whole debugging session. A macro variable defined within a macro body is created when its definition is executed and destroyed on return from the macro.

By default, macro variables are treated as signed integers and initialized to 0. When a C-SPY variable is assigned a value in an expression, it also acquires the type of that expression. For example:

Expression

What it means

myvar = 3.5;

myvar is now type double, value 3.5.

myvar = (int*)i;

myvar is now type pointer to int, and the value is the same as i.

Table 24. Examples of C-SPY macro variables 


In case of a name conflict between a C symbol and a C-SPY macro variable, C-SPY macro variables have a higher precedence than C variables. Note that macro variables are allocated on the debugger host and do not affect your application.

Macro parameters

A macro parameter is intended for parameterization of device support. The named parameter will behave as a normal C-SPY macro variable with these differences:

  • The parameter definition can have an initializer

  • Values of a parameters can be set through options (either in the IDE or in cspybat).

  • A value set from an option will take precedence over a value set by an initializer

  • A parameter must have an initializer, be set through an option, or both. Otherwise, it has an undefined value, and accessing it will cause a runtime error.

The syntax for defining one or more macro parameters is:

__param param[=value, ...;]

Use the command line option ‑‑macro_param to specify a value to a parameter, see ‑‑macro_param.

Macro strings

In addition to C types, macro variables can hold values of macro strings. Note that macro strings differ from C language strings.

When you write a string literal, such as "Hello!", in a C-SPY expression, the value is a macro string. It is not a C-style character pointer char*, because char* must point to a sequence of characters in target memory and C-SPY cannot expect any string literal to actually exist in target memory.

You can manipulate a macro string using a few built-in macro functions, for example __strFind or __subString. The result can be a new macro string. You can concatenate macro strings using the + operator, for example str + "tail". You can also access individual characters using subscription, for example str[3]. You can get the length of a string using sizeof(str). Note that a macro string is not NULL-terminated.

The macro function __toString is used for converting from a NULL-terminated C string in your application (char* or char[]) to a macro string. For example, assume this definition of a C string in your application:

char const *cstr = "Hello";

Then examine these macro examples:

__var str;         /* A macro variable */
str = cstr         /* str is now just a pointer to char */
sizeof str         /* same as sizeof (char*), typically 2 or 4 */
str = __toString(cstr,512)  /* str is now a macro string */
sizeof str         /* 5, the length of the string */
str[1]             /* 101, the ASCII code for 'e' */
str += " World!"   /* str is now "Hello World!" */

See also Formatted output.

Macro statements

Statements are expected to behave in the same way as the corresponding C statements would do. The following C-SPY macro statements are accepted:

Expressions
expression;

For more information about C-SPY expressions, see C-SPY expressions.

Conditional statements
if (expression)
  statement

if (expression)
  statement
else
  statement
Loop statements
for (init_expression; cond_expression; update_expression)
  statement

while (expression)
  statement

do
  statement
while (expression);
Return statements
return;

return expression;

If the return value is not explicitly set, signed int 0 is returned by default.

Blocks

Statements can be grouped in blocks.

{
  statement1
  statement2
  .
  .
  .
  statementN
}

Formatted output

C-SPY provides various methods for producing formatted output:

__message argList;

Prints the output to the Debug Log window.

__fmessage file, argList;

Prints the output to the designated file.

__smessage argList;

Returns a string containing the formatted output.

where argList is a comma-separated list of C-SPY expressions or strings, and file is the result of the __openFile system macro, see __openFile.

To produce messages in the Debug Log window:

var1 = 42;
var2 = 37;
__message "This line prints the values ", var1, " and ", var2, " in the Debug Log window.";

This produces this message in the Debug Log window:

This line prints the values 42 and 37 in the Debug Log window.

To write the output to a designated file:

__fmessage myfile, "Result is ", res, "!\n";

To produce strings:

myMacroVar = __smessage 42, " is the answer.";

myMacroVar now contains the string "42 is the answer.".

Specifying display format of arguments

To override the default display format of a scalar argument (number or pointer) in argList, suffix it with a : followed by a format specifier. Available specifiers are:

%b

for binary scalar arguments

%o

for octal scalar arguments

%d

for decimal scalar arguments

%x

for hexadecimal scalar arguments

%c

for character scalar arguments

These match the formats available in the Watch and Locals windows, but number prefixes and quotes around strings and characters are not printed.

Example:

__message "The character '", cvar:%c, "' has the decimal value ", cvar;

Depending on the value of the variables, this produces this message:

The character 'A' has the decimal value 65

Note

A character enclosed in single quotes (a character literal) is an integer constant and is not automatically formatted as a character. For example:

__message 'A', " is the numeric value of the character ", 'A':%c;

would produce:

65 is the numeric value of the character A

Optionally, a number can be inserted between the % and the letter, to format an integer to that minimum width. Binary, octal, and hexadecimal numbers will be left-padded with zeros, decimal numbers and characters will be padded with spaces. Note that numbers that do not fit within the requested minimum width will not be truncated.

Examples:

__message 31:%4x;     // 001f
__message 31:%4d;     //   31
__message 31:%8b;     // 00011111

Note

The default format for certain types is primarily designed to be useful in the Watch window and other related windows. For example, a value of type char is formatted as 'A' (0x41), while a pointer to a character (potentially a C string) is formatted as 0x8102 "Hello", where the string part shows the beginning of the string (currently up to 60 characters).

When printing a value of type char*, use the %x format specifier to print just the pointer value in hexadecimal notation, or use the system macro __toString to get the full string value.