Menu

#3150 sdas up-arrow escaped string fails to parse

open
nobody
None
sdas
5
2020-11-11
2020-11-10
No

asmlnk.txt documents "up-arrow (^) construction" for strings as one of the supported options:

1.4.14  .ascii, .str, and .fcc Directives
[...]
.str     /string/               or
.str    ^/string/

This is in particular needed for macro string arguments, when the string contains the argument delimiter character:

Arguments which themselves contain separating characters must be
enclosed  within  the  delimiter  construct  ^/   /  where   the
character  '/'  may be any character not in the argument string.

This seems to be broken though, I'm getting parsing errors from sdas if I try to use it, this simple example fails for me:

cat > testcase.s <<EOF
; works
.str /foo/
; caret-quoting should work, but fails
.str ^/foo/
EOF
$ sdas8051 testcase.s
testcase.s:4: Error: <q> missing or improper operators, terminators, or delimiters

As does the macro attempt:

cat > testcase.s <<EOF
.macro foo arg
.ascii arg
.endm

; works
foo /foo/
; caret-quoting should work, but fails
foo ^/foo/
EOF
$ sdas8051 testcase.s
testcase.s:8: Error: <q> missing or improper operators, terminators, or delimiters

I've tried both the trunk version and the Debian sdcc 4.0.0+dfsg-2 version, both fail to parse this.

Discussion

  • Tobias Diedrich

    Tobias Diedrich - 2020-11-10

    Debugging with

    #define qerr() do { fprintf(stderr, "qerr: %s:%d\n", __FILE__, __LINE__); qerr_real(); } while (0);
    

    shows the error is thrown in aslex.c:422:

    qerr: ../asxxsrc/aslex.c:422
    qerr: ../asxxsrc/aslex.c:422
    qerr: ../asxxsrc/aslex.c:422
    /tmp/testcase.s:8: Error: <q> missing or improper operators, terminators, or delimiters
    

    which is just

            if ((c=get()) == '\0')
                    qerr();
    

    in "int getmap(int d)"...

     
  • Tobias Diedrich

    Tobias Diedrich - 2020-11-10
    (gdb) bt
    #0  qerr_real () at ../asxxsrc/assubr.c:223
    #1  0x000055555555afa7 in getmap (d=94) at ../asxxsrc/aslex.c:422
    #2  0x000055555555deb5 in asmbl () at ../asxxsrc/asmain.c:1666
    #3  0x000055555555864b in main (argc=2, argv=<optimized out>) at ../asxxsrc/asmain.c:530
    

    Ok, this is where it gets more interesting:

                    case O_ASCIZ:
                            if ((d = getnb()) == '\0')
                                    qerr();
                            while ((c = getmap(d)) >= 0)
                                    outab(c);
                            if (mp->m_valu == O_ASCIZ)
                                    outab(0);
                            break;
    

    Looks like d is the delimiter (indeed 94 matches '^').
    I don't see any special handling for '^' here, maybe it got removed at some point? (Or never worked?)

    Even in the macro testcase, the error seems to be in the .str / .ascii parsing, so I'm guessing it passed fine through the macro.

     
  • Tobias Diedrich

    Tobias Diedrich - 2020-11-11

    Ohh, I think I get it. The first getnb() should be getdlm() instead (since it tries to get the delimiter character), which has the handling for '^'.

     
  • Tobias Diedrich

    Tobias Diedrich - 2020-11-11

    If I do that change though there is some weirdness:
    works:

    .macro bar arg
    .ascii arg
    .endm
    bar /foo/
    

    also works with the change:

    .macro bar arg
    .ascii ^/arg/
    .endm
    bar ^/foo/
    

    doesn't work:

    .macro bar arg
    .ascii arg
    .endm
    bar ^/foo/
    

    also doesn't work:

    .macro bar arg
    .ascii ^/arg/
    .endm
    bar /foo/
    

    it seems like in the macro invocation, for the '^' special case, the delimiters are not passed
    on into the macro, while without '^' they are...

     
  • Tobias Diedrich

    Tobias Diedrich - 2020-11-11

    But basically the change I made is:

    Index: sdas/asxxsrc/asmain.c
    ===================================================================
    --- sdas/asxxsrc/asmain.c       (revision 11952)
    +++ sdas/asxxsrc/asmain.c       (working copy)
    @@ -1661,7 +1661,7 @@
                     switch(mp->m_valu) {
                     case O_ASCII:
                     case O_ASCIZ:
    
    -                        if ((d = getnb()) == '\0')
    +                        if ((d = getdlm()) == '\0')
                                     qerr();
                             while ((c = getmap(d)) >= 0)
                                     outab(c);
    @@ -1670,7 +1670,7 @@
                             break;
    
                     case O_ASCIS:
    
    -                        if ((d = getnb()) == '\0')
    +                        if ((d = getdlm()) == '\0')
                                     qerr();
                             c = getmap(d);
                             while (c >= 0) {
    
     

Log in to post a comment.

MongoDB Logo MongoDB