<-- previous page Table of Contents Index next page -->

## Macros

### Simple Macros (without parameters)

Macros can be defined to avoid retyping or to give mnemonic names to things. A macro is defined with the following syntax:

    define  macro_name macro_text @

The macro_name consists of one or more upper case letters, digits, and underscores, with the first character being a letter. The macro_text can be any text. It can be any length from empty to many pages. The "@" terminates the macro. A literal "@" can be placed in the macro_text by preceding it with a backslash. If you want a literal backslash in the macro_text, it also must be preceded by a backslash.

A macro is called by stating the macro_name in the input. The macro_name is replaced by the macro_text. A macro can be defined at any point in the input. It can be used as often as desired any time after it has been defined. A given macro_name can be redefined as many times as desired, with each new definition overwriting the previous definition.

As an example, suppose you are printing an orchestral score, and the oboe part happens to be on staff 5. Rather than having to remember which staff it is, you could define a macro:

    define OBOE 5: @

Not only is the name easier to remember than a number, but if you later decide to move the oboe part to a different place in the score, only the macro definition and perhaps a few other things would have to be changed.

Another common use of macros might be if a musical motif occurs several times. You could define a macro for the motive:

    define SCALE 8c;d;e;f;g;a;b;c+; @

then do something like:

    OBOE SCALE

It is possible to remove the definition of a macro using the "undef" statement:

    undef OBOE

It is possible to have parts of the input skipped over depending on whether certain macros are defined or not. This is done using "ifdef," "else," and "endif." The keyword "ifdef" is followed by a macro name. If a macro by that name is currently defined, Mup will continue reading and processing input normally. If it finds a matching "else," it will skip over input until the matching "endif." If the macro is not currently defined, Mup will skip over the input until it finds a matching "else" or "endif." There is also an "ifndef" command that uses the opposite logic: it will read the input up to the "else" or "endif" only if the macro is NOT defined.

The ifdefs can be sprinkled between other items in the input; they need not be on separate lines. They can be nested. Examples:

    // make last c an octave higher if macro "FRED" is defined
    1: c;e;g;c ifdef FRED + endif;

    ifdef PIANO
        staff 1 visible=n
    else
        ifdef VIOLIN
            staff 2 visible=n
            staff 3 visible=n
        endif
    endif

Macros can also be set from the command line using the -D option. Only ordinary macros can be defined using the -D option, not macros with parameters.

### Macros with parameters

Macros defined within Mup input can be defined to have "parameters." This may be useful when you have something that is repeated with small variations. When defining a macro with parameters, the macro name must be followed immediately by a ( with no space between the end of the name and the parenthesis. The opening parenthesis is followed by one or more parameter names, separated by commas, and ending with a close parenthesis. Parameter names have the same rules as macro names: they consist of upper case letters, numbers, and underscores, starting with an upper case letter. The parameter names can then appear in the text of the macro definition where you want a value to be substituted.

As an example, suppose you are doing a score with staffs 1 through 4 for vocal parts, and staffs 5 and 6 for a piano accompaniment, and that you frequently want to mark a dymanics change at the same point in time below each of the vocal scores and between the two piano staffs. You could typically do this with something like:

    boldital below 1-4: 1 "ff";
    boldital between 5&6: 1 "ff";

but if you needed to do this lots of times, it could get tedious. So let's define a macro with parameters:

    define DYN( COUNT, VOLUME )
    boldital below 1-4: COUNT VOLUME;
    boldital between 5&6: COUNT VOLUME;
    @

This macro has two parameters, which have been given the names COUNT and VOLUME. When you call the macro, you will give them values. For example,

    DYN(1,"ff")

would give a VOLUME of "ff" at COUNT 1, whereas

    DYN(3.5,"mp")

would give a VOLUME of "mp" at COUNT 3.5.

When calling a macro with parameters, the values to give the parameters are given inside parentheses. The values are separated by commas. The values in the parentheses are copied exactly as they are, including any spaces, newlines, macro names, etc. There are only a few exceptions to this: you can include a comma, closing parenthesis, or backslash as part of a parameter value by preceding it with a backslash, and a backslash followed by a newline in a parameter value will be discarded. Thus a macro call of

    MAC(\\\,\))

has one parameter, the text of which is 3 characters long: a backslash, comma, and closing parenthesis.

If in a macro definition a parameter is used inside backticks, as in `NAME`, the value of the parameter will be placed inside double quotes. Thus, another way to do the example above would be:

    define DYN( COUNT, VOLUME )
    boldital below 1-4: COUNT `VOLUME`;
    boldital between 5&6: COUNT `VOLUME`;
    @

    DYN(1,ff)
    DYN(3.5,mp)

Conceptually, when the macro is expanded, the backticks are replaced by double quote marks, but in addition, any double quote mark found in the value being passed to the parameter will have a backslash inserted before it, and any backslash that occurs within double quotes in the value will also have a backslash inserted before it. Thus, for example:

    // If we define a macro like this:
    define QUOTED(X) `X` @

    // then for input    value passed is    `X` would be    which would print as

    print QUOTED(hello)       hello          "hello"          hello
    print QUOTED("hello")     "hello"        "\"hello\""      "hello"
    print QUOTED(\\n)         \n             "\n"             a literal newline
    print QUOTED("\\n")       "\n"           "\"\\n\""        "\n"

Sometimes it can be a little tricky to get the number of backslashes right, or other details like that. The -E Mup command line option shows how macros will expand, which may help you figure out what to do.

<-- previous page Table of Contents Index next page -->