Menu

#100 New Preprocessor Directives (diff attached)

open
nobody
1
2005-09-22
2005-09-22
Anonymous
No

I needed some new preprocessor directives for some macros I wanted
to make. The two new directives are %string and %delete.

%string works similar to %xdefine, except that whatever's on the right
hand side is converted to a string.

%delete works like %undef, except that where %undef will delete the
single line macro it's given as an operand, %delete expands it as far as
it will expand and deletes what it expands to. Naturally, as an expanded
macro is no longer a macro identifier, I also had to make %undef and %
delete accept strings as input.

I added these macros to make it possible for macros to create and later
delete other macros. E.g.:

%macro create 2
%push silly
%string %$var %1
%define %1 %2
%endmacro

%macro destroy 0
%delete %$var
%pop
%endmacro

So "create x, 12" will "%define x 12" and then "destroy" will basically "%
undef x". This wasn't possible before, since %undef wouldn't ever
expand a macro, and even if it did, %$var would expand to x which
would expand to 12.

Anyway, my patch has bugs. At the very least it makes NASM segfault if
you try to %undef %$v1 when there isn't a %$v1. I can't figure out what
I did to make it do that. Everything else seems to work just fine, though,
so I don't know what I did. (I also just learned C two weeks ago.) I
wouldn't have even bothered trying to make a patch, except that there
seems to be a mile long list of feature requests here, and I wanted to
give mine a better chance of being added to NASM sometime in the near
future.

Anyway, a diff should be attached, and my email address is peajay at
funrestraints dot com if you need to email me.

Discussion

  • Nobody/Anonymous

    Logged In: NO

    Nice, it didn't upload my diff. Well, I'll stick it on my website, here's a link:

    http://xerse.nfshost.com/secret/nasmdiff

     
  • nasm64developer

    nasm64developer - 2005-09-22

    Logged In: YES
    user_id=804543

    Take a look at SF RFE #829879. It suggests %# as a
    means for preventing the expansion of a single-line
    macro. The required changes are small.

    Also note that you can already "stringify" tokens
    as long as you can live with "unterminated string"
    warnings (which should be made suppressible -- but
    that's another issue).

    %MACRO AddSingleQuotes 2+
    %PUSH local
    %XDEFINE %$single '
    %XDEFINE %1 %$single%2%$single
    %POP
    %ENDMACRO

    %MACRO AddDoubleQuotes 2+
    %PUSH local
    %XDEFINE %$double "
    %XDEFINE %1 %$double%2%$double
    %POP
    %ENDMACRO

    AddSingleQuotes TEMP1,%!TEMP
    AddDoubleQuotes TEMP2,%!TEMP

    db TEMP1
    db TEMP2

    Last but not least, a "cleaner" solution would add
    both %TOK2STR and %STR2TOK, to perform conversion
    between token(s) and strings. (That is, your %STRING
    should be accompanied by its opposite directive.)

     
  • nasm64developer

    nasm64developer - 2005-09-22
    • priority: 5 --> 1
     
  • Nobody/Anonymous

    Logged In: NO

    > Take a look at SF RFE #829879

    While I guess that would work, I like my solution better for these reasons:

    The %string directive is useful for other things as well, for example I also
    wrote a macro to call procedures, like "proccall function, x, [y]" which wants to
    see if the first character of each operand is '[' so that it knows if it's dealing
    with an effective address or not, but in order to use %substr, the parameters
    first have to be strings.

    So since there would be a %string directive for other purposes, then simply
    allowing strings as operands to %undef and %delete (as well as all of the
    other directives) seems like a more logical way of passing unexpandable
    macro identifiers to them. It doesn't require creation of a new token type, but
    instead uses one which was otherwise invalid in those contexts. Not to
    mention, it just makes sense that %undef 'mac' should delete the macro mac
    instead of complain about an invalid operand. As an added bonus, 'mac' is a
    lot easier to look at than %#mac.

    %delete is still necessary in either case, for example, with the create and
    destroy macros from above, "create x" would do "%define %$var %#%1" and,
    if I understand things correctly, the %1 would expand despite the %# being in
    front of it, so that "%#x" would be assigned to %$var. (If it doesn't, then %#
    won't work as a replacement for my solution.) However, then in the destroy
    macro, changing "%delete %$var" to "%undef %$var" won't expand %$var into
    %#x. We could get around this by writing a delete macro, since the
    expansion would occur in the macro call, however, having %delete seems a lot
    nicer than making people have to make their own delete macro.

    Anyway, the "%xdefine %$single '" thing is an interesting hack, but it seems
    like relying on the fact that NASM will assign a value to %$string despite the
    error, and I don't like depending on the results of errors.

    The best hack-type solution I came up with was to do this:

    %define save %1
    %define %1 %1 + ebp + 8
    %1 equ 0

    Which makes whatever %1 was (say it was 'var') expand to "var + ebp + 8",
    and then expansion stops there to prevent recursion, and the assembler treats
    var as 0, so it's effectively ignored. Then to delete it you do this:

    delete save

    Where delete is a macro that does an %undef, so that "save" becomes "var +
    ebp + 8" and %undef deletes "var", while complaining about extra garbage
    after the macro identifier.

    That almost worked, but hacked solutions have a way of falling apart under the
    right conditions, and so did that solution. Say I had a macro like this:

    %macro proccall 1-*
    %rep %0 - 1
    %rotate -1
    push %1
    %endrep
    %rotate -1
    call %1
    add esp, 4 * %0 - 4
    %endmacro

    In that case, when I passed 'var' to it, it would expand to "var + ebp + 8" and
    then later when the push instruction was generated, it would expand again, to
    "var + ebp + 8 + ebp + 8".

    Also, during the six hours of trying to make this work without NASM
    modifications, I discovered that this:

    %xdefine x y
    %define y z

    Makes macro x work exactly the same as it would if I had done this:

    %define x y
    %define y z

    While I understand why it does that, it does seem contrary to the intended
    purpose of %xdefine. It could be corrected with some sort of flag to mark the
    contents of macro x as unexpandable when x is defined with %xdefine, and in
    doing so it would also remove the need for %string and %#, since you could
    do this instead:

    %xdefine x y
    %define y z
    %delete x

    And the "%delete x" would expand to "%delete y", but 'y' wouldn't expand to
    'z' since the contents of 'x' are unexpandable, and so it would "%delete y" as
    desired.

    It seems easy enough to do, when you're expanding macros, simply don't
    expand %xdefine'd macros until all of the other macros are expanded, then
    expand them but don't look at the string again after that. However, I'm not sure
    if such a modification to %xdefine's behavior would be desireable or not.

    > would add both %TOK2STR and %STR2TOK

    Should I assume then that it will be called %tok2str, and go ahead and update
    my code to reflect that?

     
  • nasm64developer

    nasm64developer - 2005-09-22

    Logged In: YES
    user_id=804543

    > [%STRING is useful]

    Absolutely.

    > [directives that accept identifiers should accept strings]

    As an additional twist, imagine that the preprocessor were
    capable of expanding identifiers handed to directives. That
    is, accept identifiers, preprocessor identifiers, numbers,
    as well as tokens which result in token separation, token
    concatenation, prohibition of smac expansion, or recursion.
    (If you look through the various SF RFEs: %<, %>, %#, %^.)
    In other words: the final identifier can be the result of
    various operations.

    Don't choke, but I've got such a beast. :-)

    > [%DELETE]

    I need to think about this one some more.

    > [%TOK2STR and %STR2TOK]

    I merely wanted to point out that these form a pair, and
    which names I picked for them.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.