#112 Figure brackets enclosure


Multiline macro expander doesn't handle square brackets

%define foo1(x) x

%macro foo2 1-*
%error %1

%error foo1( {1, {2}, 3} ) ; result: 1, {2}, 3
foo2 {1, {2}, 3} ; result: 1, {2

This is bug, I suppose, and I'll fix it.
Current behaviour doesn't allow some interesting syntax,
like hierachical structure initialization:

;foo structure definition:
;foo.a, foo.b, foo.bar.a, foo.bar.b, foo.c

initstruc foo, {v1, v2, {v3, v4}, v5}


    • labels: --> Preprocessor Bugs
    • assigned_to: nobody --> unv
  • Logged In: YES

    Yeah, preproc.c's count_mmac_params() and expand_mmacro()
    functions don't count opening/closing curly braces, like
    the expand_smacro() function does. Which is why -- as of
    writing this -- one can't pass "{.+}" as an argument to
    a multi-line macro, i.e. a closing curly brace.

  • Logged In: YES

    As noted by Nickolay, a comma between the arguments of
    a single-line macro invocation didn't act like a "}",
    and thus lead to incorrect argument treatment. The fix
    is to set brackets to 0 just after the 2nd of the three
    occurences of "white = 0;" in preproc.c.

    With that bug out of the way, I'll look at multi-line
    macro arguments and curly braces next.

  • Logged In: YES

    I've redesigned a bit multiline macro expansion - now only
    count_mmac_params() counts and demarcates parameters.
    And does it correctly. I've also renamed is_mmacro() to
    get_mmacro(), which returns full-formed multiline macro
    reference with filled parameters array (this is not in CVS yey,
    of course - it's for Nasm 0.99).

  • Logged In: YES

    Since Nickolay's re-write of preproc.c isn't likely
    to be accepted until it has been (a) spec'd/approved
    and (b) thoroughly verified by a substantial number
    of users and developers, I have started to work on a
    fix for the existing preproc.c, that can be used in
    the meantime.

    I think that I've got it, but I want to do some more
    testing first.

    So stay tuned...

  • Logged In: YES

    I've got everything to work, except for one case.

    How does one pass the opening curly brace '{' as
    an argument to a single-line macro?

    In case of a multi-line macro it can be done, as
    long as it is the last argument.

    However, in case of a single-line macro there has
    to be a closing parenthesis. Which, if preceded by
    an opening curly brace, just becomes part of that
    last (literal) argument and thus causes an error
    due to a missing closing parenthesis.

    All those curly braces made my head hurt... 8-)

    Let me know if you're interested in my testcases.

  • Logged In: YES

    I have found the answer to my question.

    Since single-line macro arguments are counted before
    they are expanded, the opening curly brace '{' can be
    passed as a single-line macro argument by "wrapping"
    it in another single-line macro, like so:

    %define oc {
    %define smac(x) x
    %error [smac(oc)] ; filename.asm:3: warning: [{]

    Btw, the same trick won't work for multi-line macro
    arguments, because single-line macros are expanded
    before multi-line macros are. That is, a multi-line
    macro would see '{' instead of 'oc'.

    However, with my upcoming fixes one can pass '{{'
    as the last argument of a multi-line macro -- this
    will result in '{'.

    That said, I'm in the process of wrapping up those
    fixes; I'll post them shortly. As well as all the
    testcases I've come up with.

  • Logged In: YES

    I've posted my changes and testcases to the nasm-devel
    list, since I can't seem to attach them here.

  • Logged In: YES

    I don't think we should use such hacks for '{' itself. This is a
    control token anyway. And it should have a pair - otherwise
    error must be given. If we want to use it as usual token we
    should add escape syntax (like \{ ). But I think if someone
    wants to pass safely complex token list into a multiline macro
    he can use following syntax:

    %define oc {
    %define smac(x) x
    foo %detok(smac(x)) ; foo "{"

    where foo is:

    %macro foo 1
    %xdefine param1 %strtok(%1)

    We'll get the expected result.

    And one even may pass something monsterous in this way:
    foo "{(,{)[]"

  • Logged In: YES

    Yes, normally curly braces should be used in pairs and
    the outer-most pair should enclose an entire parameter.

    However, there are occasions when I need to pass single
    opening or closing curly braces to a single- or multi-
    line macro. For example, during my debug output macros.

    I did consider adding support for a more generic escape
    mechanism a la backslash (and in fact had to do so for
    the primitive assembler directives, to be able to use a
    closing square bracket in an argument), but shied away
    from attempting such an intrusive overall change, which
    would have rammifications in many places through NASM.

    So, instead I ended up relying on existing NASM behavior
    as mentioned in my previous update to this bug report.

    On a side note...

    For now I've got to live with the existing preprocessor,
    not one that may one day supersede it... or not. To me a
    step by step improvement is way more valuable, than one
    big fat re-write, which I can't verify in any reasonable
    amount of time. Read: %DETOK, %STRTOK, or function-like
    syntax are -- as of writing this -- not an option to me.

    It's kinda like when someone suggests "use YASM". ;-)

  • Logged In: YES

    I just ask you not to introduce any doubtful behaviour as
    usual for Nasm. This syntax is unsafe. How will you pass '}' to
    the macro?

    > For now I've got to live with the existing preprocessor,
    > not one that may one day supersede it... or not.

    No, not supersede - extend the right word. And fix a lot of
    bugs. I've sent a lot of comments with it in my last 'preproc.c'
    message (but I cannot see attaches in the mail list).
    Step-by-step improvement is slow. After a lot of patches
    preprocessor had to be refactored.

  • Logged In: YES

    > I just ask you not to introduce any doubtful
    > behaviour as usual for Nasm.

    I didn't introduce any new behavior.

    I just tried to fix the existing one that was broken.

    > This syntax is unsafe.


    I never claimed that the curly brace solution is ideal.

    > How will you pass '}' to the macro?

    Check out the testcases I posted earlier.

    In particular, read the comments they contain.

    As for the pros and cons of your massive preprocessor
    work -- that's a separate debate, which doesn't really
    belong into this particular bug report. I should not
    have brought it up here -- my apologies for doing so.

  • Logged In: YES

    During single line macro function call '{' and '}' enclosure
    would be counted only if '{' is in the start of parameter:
    foo({a}) ; a
    foo(\{a}) ; \{a}
    So, escape syntax already exists. I think, the same must be
    done with multiline macro.

    • status: open --> open-works-for-me
    • priority: 5 --> 1