cscanf

Negating brackets in a C scanf() scanset


I'm trying to use scanf() to read lines of the form mov r0, r1, r2 or ldr r0, [r1, 0x4] in a text buffer, negating any possible square brackets, commas and white spaces. The following code is not working:

void ReadBuffer(const char* buffer)
{
 char command[2048];
 char var[3][2048];
 sscanf(buffer,"%[^ ,[]\n\t] %[^ ,[]\n\t], %[^ ,[]\n\t], %[^ ,[]\n\t]", command, va[0], var[1], var[2]);
}

How can I add the square brackets to the negated scanset?


Solution

  • C 2018 describes the scanf conversion specifiers in 7.21.6.2 12, and for the [ conversion it says:

    … If the conversion specifier begins with [] or [^], the right bracket character is in the scanlist and the next following right bracket character is the matching right bracket that ends the specification; otherwise the first following right bracket character is the one that ends the specification…

    Therefore, put the ] immediately after the ^. The [ may go anywhere in the scanlist (the characters between the [ and the closing ]).

    Example:

    #include <stdio.h>
    
    
    int main(void)
    {
        char a[100], b, c[100], d, e[100], f;
        int result = sscanf("foo[bar, baz]", " %[^][, ] %c %[^][, ] %c %[^][, ] %c", a, &b, c, &d, e, &f);
        printf("scanf returned %d.\n", result);
        printf("a = %s.\n", a);
        printf("b = %c.\n", b);
        printf("c = %s.\n", c);
        printf("d = %c.\n", d);
        printf("e = %s.\n", e);
        printf("f = %c.\n", f);
    }
    

    Output:

    scanf returned 6.
    a = foo.
    b = [.
    c = bar.
    d = ,.
    e = baz.
    f = ].
    

    Note this is a painstaking way to parse assembly code. It is usually better to write your own C code to analyze the characters, especially after studying some parsing theory, and even better to use an off-the-shelf lexical analyzer generator and a grammar parser generator. Doing it with scanf requires careful attention to return values, buffer sizes, and more.