Esempio n. 1
0
struct sr_java_frame *
sr_java_frame_parse(const char **input,
                     struct sr_location *location)
{
    const char *mark = *input;
    int lines, columns;
    /*      at SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */
    const char *cursor = sr_strstr_location(mark, "at", &lines, &columns);

    if (!cursor)
    {
        location->message = "Frame expected";
        return NULL;
    }

    /*  SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */
    cursor = mark = cursor + 2;
    sr_location_add(location, lines, columns + 2);

    /* SimpleTest.throwNullPointerException(SimpleTest.java:36) [file:/usr/lib/java/foo.class] */
    cursor = sr_skip_whitespace(cursor);
    sr_location_add(location, 0, cursor - mark);
    mark = cursor;

    sr_location_add(location, 0, sr_skip_char_cspan(&cursor, "(\n"));

    struct sr_java_frame *frame = sr_java_frame_new();

    if (cursor != mark)
        frame->name = sr_strndup(mark, cursor - mark);

    /* (SimpleTest.java:36) [file:/usr/lib/java/foo.class] */
    if (*cursor == '(')
    {
        ++cursor;
        sr_location_add(location, 0, 1);
        mark = cursor;

        sr_location_add(location, 0, sr_skip_char_cspan(&cursor, ":)\n"));

        if (mark != cursor)
        {
            if (sr_java_frame_parse_is_native_method(mark))
                frame->is_native = true;
            else if (!sr_java_frame_parse_is_unknown_source(mark))
            {
                /* DO NOT set file_name if input says that source isn't known */
                frame->file_name = sr_strndup(mark, cursor - mark);
                frame->file_name = anonymize_path(frame->file_name);
            }
        }

        if (*cursor == ':')
        {
            ++cursor;
            sr_location_add(location, 0, 1);
            mark = cursor;

            sr_parse_uint32(&cursor, &(frame->file_line));

            sr_location_add(location, 0, cursor - mark);
        }
    }

    /* [file:/usr/lib/java/foo.class] */
    mark = sr_java_frame_parse_frame_url(frame, cursor, location);
    cursor = strchrnul(mark, '\n');

    if (*cursor == '\n')
    {
        *input = cursor + 1;
        sr_location_add(location, 2, 0);
    }
    else
    {
        *input = cursor;
        /* don't take \0 Byte into account */
        sr_location_add(location, 0, (cursor - mark) - 1);
    }

    return frame;
}
Esempio n. 2
0
struct sr_ruby_frame *
sr_ruby_frame_parse(const char **input,
                    struct sr_location *location)
{
    const char *local_input = *input;
    struct sr_ruby_frame *frame = sr_ruby_frame_new();

    /* take everything before the backtick
     * /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     */
    char *filename_lineno_in = NULL;
    if (!sr_parse_char_cspan(&local_input, "`", &filename_lineno_in))
    {
        location->message = sr_strdup("Unable to find the '`' character "
                                      "identifying the beginning of function name.");
        goto fail;
    }

    size_t l = strlen(filename_lineno_in);
    location->column += l;

    char *p = filename_lineno_in + l;

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                           ^^^^
     */
    p -= strlen(":in ");
    if (p < filename_lineno_in || 0 != strcmp(":in ", p))
    {
        location->column -= strlen(":in ");
        location->message = sr_strdup("Unable to find ':in ' preceding the "
                                      "backtick character.");
        goto fail;
    }

    /* Find the beginning of the line number. */
    *p = '\0';
    do {
        p--;
    } while (p >= filename_lineno_in && isdigit(*p));
    p++;

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                         ^^
     */
    char *p_copy = p;
    int lineno_len = sr_parse_uint32((const char **)&p_copy, &frame->file_line);
    if (lineno_len <= 0)
    {
        location->message = sr_strdup("Unable to find line number before ':in '");
        goto fail;
    }

    /* /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
     *                                                        ^
     */
    p--;
    if (p < filename_lineno_in || *p != ':')
    {
        location->column -= lineno_len;
        location->message = sr_strdup("Unable to fin the ':' character "
                                      "preceding the line number");
        goto fail;
    }

    /* Everything before the colon is the file name. */
    *p = '\0';
    frame->file_name = filename_lineno_in;
    filename_lineno_in = NULL;

    if(!sr_skip_char(&local_input, '`'))
    {
        location->message = sr_strdup("Unable to find the '`' character "
                                      "identifying the beginning of function name.");
        goto fail;
    }

    location->column++;

    /* The part in quotes can look like:
     * `rescue in rescue in block (3 levels) in func'
     * parse the number of rescues and blocks
     */
    while (sr_skip_string(&local_input, "rescue in "))
    {
        frame->rescue_level++;
        location->column += strlen("rescue in ");
    }

    if (sr_skip_string(&local_input, "block in "))
    {
        frame->block_level = 1;
        location->column += strlen("block in");
    }
    else if(sr_skip_string(&local_input, "block ("))
    {
        location->column += strlen("block (");

        int len = sr_parse_uint32(&local_input, &frame->block_level);
        if (len == 0 || !sr_skip_string(&local_input, " levels) in "))
        {
            location->message = sr_strdup("Unable to parse block depth.");
            goto fail;
        }
        location->column += len + strlen(" levels) in ");
    }

    if (sr_skip_char(&local_input, '<'))
    {
        location->column++;
        frame->special_function = true;
    }

    if (!sr_parse_char_cspan(&local_input, "'>", &frame->function_name))
    {
        location->message = sr_strdup("Unable to find the \"'\" character "
                                      "delimiting the function name.");
        goto fail;
    }
    location->column += strlen(frame->function_name);

    if (frame->special_function)
    {
        if (!sr_skip_char(&local_input, '>'))
        {
            location->message = sr_strdup("Unable to find the \">\" character "
                                          "delimiting the function name.");
            goto fail;
        }
        location->column++;
    }

    if (!sr_skip_char(&local_input, '\''))
    {
        location->message = sr_strdup("Unable to find the \"'\" character "
                                      "delimiting the function name.");
        goto fail;
    }
    location->column++;

    *input = local_input;
    return frame;

fail:
    sr_ruby_frame_free(frame);
    free(filename_lineno_in);
    return NULL;
}
Esempio n. 3
0
struct sr_python_frame *
sr_python_frame_parse(const char **input,
                      struct sr_location *location)
{
    const char *local_input = *input;

    if (0 == sr_skip_string(&local_input, "  File \""))
    {
        location->message = sr_asprintf("Frame header not found.");
        return NULL;
    }

    location->column += strlen("  File \"");
    struct sr_python_frame *frame = sr_python_frame_new();

    /* Parse file name */
    if (!sr_parse_char_cspan(&local_input, "\"", &frame->file_name))
    {
        location->message = sr_asprintf("Unable to find the '\"' character "
                "identifying the beginning of file name.");

        goto fail;
    }

    if (strlen(frame->file_name) > 0 &&
        frame->file_name[0] == '<' &&
        frame->file_name[strlen(frame->file_name)-1] == '>')
    {
        frame->special_file = true;
        frame->file_name[strlen(frame->file_name)-1] = '\0';
        char *inside = sr_strdup(frame->file_name + 1);
        free(frame->file_name);
        frame->file_name = inside;
    }

    frame->file_name = anonymize_path(frame->file_name);

    location->column += strlen(frame->file_name);

    if (0 == sr_skip_string(&local_input, "\", line "))
    {
        location->message = sr_asprintf("Line separator not found.");
        goto fail;
    }

    location->column += strlen("\", line ");

    /* Parse line number */
    int length = sr_parse_uint32(&local_input, &frame->file_line);
    if (0 == length)
    {
        location->message = sr_asprintf("Line number not found.");
        goto fail;
    }

    location->column += length;

    if (0 == sr_skip_string(&local_input, ", in "))
    {
        if (local_input[0] != '\n')
        {
            location->message = sr_asprintf("Function name separator not found.");
            goto fail;
        }

        /* The last frame of SyntaxError stack trace does not have
         * function name on its line. For the sake of simplicity, we will
         * believe that we are dealing with such a frame now.
         */
        frame->function_name = sr_strdup("syntax");
        frame->special_function = true;
    }
    else
    {
        location->column += strlen(", in ");

        /* Parse function name */
        if (!sr_parse_char_cspan(&local_input, "\n", &frame->function_name))
        {
            location->message = sr_asprintf("Unable to find the newline character "
                    "identifying the end of function name.");

            goto fail;
        }

        location->column += strlen(frame->function_name);

        if (strlen(frame->function_name) > 0 &&
            frame->function_name[0] == '<' &&
            frame->function_name[strlen(frame->function_name)-1] == '>')
        {
            frame->special_function = true;
            frame->function_name[strlen(frame->function_name)-1] = '\0';
            char *inside = sr_strdup(frame->function_name + 1);
            free(frame->function_name);
            frame->function_name = inside;
        }
    }

    if (sr_skip_char(&local_input, '\n'))
        sr_location_add(location, 1, 0);

    /* Parse source code line (optional). */
    if (4 == sr_skip_string(&local_input, "    "))
    {
        if (sr_parse_char_cspan(&local_input, "\n", &frame->line_contents)
                && sr_skip_char(&local_input, '\n'))
            sr_location_add(location, 1, 0);
    }

    *input = local_input;
    return frame;

fail:
    sr_python_frame_free(frame);
    return NULL;
}