def _parse_key(to_parse):
    """Parse key, value combination
    return (tuple):
        Number of characters parsed from to_parse
        Parsed key (string)
    """
    if _DEBUG:
        print_red('key')
        print_red(to_parse)

    buf = ''
    i = 0
    key = ''
    while i < len(to_parse) - 1:
        c = to_parse[i]
        if c == '=':
            key = buf
            # consume '=' sign so caller doesn't get it again
            i += 1
            break
        buf += c
        i += 1
    if _DEBUG:
        print_green(key)
    return i, key
def _parse_dict(to_parse):
    """Parse dictionary, with optional starting character '{'
    return (tuple):
        Number of characters parsed from to_parse
        Parsed dictionary
    """
    if _DEBUG:
        print_red('obj')
        print_red(to_parse)
    i = 0
    obj = {}
    while i < len(to_parse):
        c = to_parse[i]
        if c in _WHITESPACE:
            pass
        elif c in ['{', ',']:
            pass
        elif c == '}':
            # end of object, exit loop
            break
        else:
            chars_used, key, val = _parse_key_val(to_parse[i:])
            i = i + chars_used
            obj[key] = val
        i += 1
    if _DEBUG:
        print_green(obj)
    return i, obj
Beispiel #3
0
def _parse_array(stream):
    """Parse an array, stream should be passed the initial [
    returns:
        Parsed array
    """

    if _DEBUG:
        print_green('parsing array')
    arr = []
    while True:
        c = stream.read(1)

        if c in _GDB_MI_VALUE_START_CHARS:
            stream.seek(-1)
            val = _parse_val(stream)
            arr.append(val)
        elif c in _WHITESPACE:
            pass
        elif c == ',':
            pass
        elif c == ']':
            # Stop when this array has finished. Note
            # that elements of this array can be also be arrays.
            break

    if _DEBUG:
        print('parsed array:')
        print_green(arr)
    return arr
Beispiel #4
0
def _get_notify_msg_and_payload(result, stream):
    """Get notify message and payload dict"""
    token = stream.advance_past_chars(['=', '*'])
    token = int(token) if token != '' else None
    if _DEBUG:
        print_green('parsing message')
    message = stream.advance_past_chars([','])
    if _DEBUG:
        print('parsed message')
        print_green(message)

    payload = _parse_dict(stream)
    return token, message.strip(), payload
def _parse_str(to_parse):
    """Parse a string
    return (tuple):
        Number of characters parsed from to_parse
        Parsed string, without surrounding quotes
    """

    # characters that gdb escapes that should not be
    # escaped by this parser
    CHARS_TO_REMOVE_GDB_ESCAPE = ['"']

    if _DEBUG:
        print_red('string')
        print_red(to_parse)

    assert_match(_GDB_MI_CHAR_STRING_START, to_parse[0])
    i = 1  # Skip the opening quote
    buf = ''
    while i < len(to_parse) - 1:
        c = to_parse[i]
        if _DEBUG:
            print_cyan(c)

        if c == '\\' and i < (len(to_parse) - 1):
            # We are on a backslash and there is another character after the backslash
            # to parse. Handle this case specially since gdb escaped it for us

            # Get the next char that is being escaped
            c2 = to_parse[i + 1]
            if c2 in CHARS_TO_REMOVE_GDB_ESCAPE:
                # only store the escaped character in the buffer; don't store the backslash
                # (don't leave it escaped)
                buf += to_parse[i + 1]
            else:
                # store the backslash and the following character in the buffer (leave it escaped)
                buf += c + to_parse[i + 1]

            # consume the backslash and the next character
            i += 2

        else:
            # Quote is closed. Exit (and don't include the end quote).
            if c == '"':
                break
            buf += c
            i += 1

    string = buf
    if _DEBUG:
        print_green(string)
    return i, string
def _parse_dict(to_parse):
    """Parse dictionary, with optional starting character '{'
    return (tuple):
        Number of characters parsed from to_parse
        Parsed dictionary
    """
    if _DEBUG:
        print_red('obj')
        print_red(to_parse)
    i = 0
    obj = {}
    while i < len(to_parse):
        c = to_parse[i]
        if c in _WHITESPACE:
            pass
        elif c in ['{', ',']:
            pass
        elif c == '}':
            # end of object, exit loop
            break
        else:
            chars_used, key, val = _parse_key_val(to_parse[i:])
            i = i + chars_used
            if key in obj:
                # This is a gdb bug. We should never get repeated keys in a dict!
                # See https://sourceware.org/bugzilla/show_bug.cgi?id=22217
                # and https://github.com/cs01/pygdbmi/issues/19
                # Example:
                #   thread-ids={thread-id="1",thread-id="2"}
                # Results in:
                #   thread-ids: {{'thread-id': ['1', '2']}}
                # Rather than the lossy
                #   thread-ids: {'thread-id': 2}  # '1' got overwritten!
                if isinstance(obj[key], list):
                    obj[key].append(val)
                else:
                    obj[key] = [obj[key], val]
            else:
                obj[key] = val
        i += 1
    if _DEBUG:
        print_green(obj)
    return i, obj
def _parse_key_val(to_parse):
    """Parse key, value combination
    return (tuple):
        Number of characters parsed from to_parse
        Parsed key (string)
        Parsed value (either a string, array, or dict)
    """
    if _DEBUG:
        print_red('keyval')
        print_red(to_parse)

    i = 0
    size, key = _parse_key(to_parse[i:])
    i += size
    size, val = _parse_val(to_parse[i:])
    i += size
    if _DEBUG:
        print_green(key)
        print_green(val)
    return i, key, val
def _parse_val(to_parse):
    """Parse value from string
    return (tuple):
        Number of characters parsed from to_parse
        Parsed value (either a string, array, or dict)
    """
    if _DEBUG:
        print_red('val')
        print_red(to_parse)

    i = 0
    val = ''
    buf = ''
    while i < len(to_parse) - 1:
        c = to_parse[i]

        if c == '{':
            # Start object
            size, val = _parse_dict(to_parse[i:])
            i += size
            break
        elif c == '[':
            # Start of an array
            size, val = _parse_array(to_parse[i:])
            i += size
            break
        elif c == '"':
            # Start of a string
            size, val = _parse_str(to_parse[i:])
            i += size
            break
        else:
            buf += c
        i += 1

    if _DEBUG:
        print_green(val)
    return i, val
Beispiel #9
0
def _parse_dict(stream):
    """Parse dictionary, with optional starting character '{'
    return (tuple):
        Number of characters parsed from to_parse
        Parsed dictionary
    """
    obj = {}

    if _DEBUG:
        print_green("parsing dict")
    while True:
        c = stream.read(1)
        if c in _WHITESPACE:
            pass
        elif c in ["{", ","]:
            pass
        elif c in ["}", ""]:
            # end of object, exit loop
            break

        else:
            stream.seek(-1)
            key, val = _parse_key_val(stream)
            if key in obj:
                # This is a gdb bug. We should never get repeated keys in a dict!
                # See https://sourceware.org/bugzilla/show_bug.cgi?id=22217
                # and https://github.com/cs01/pygdbmi/issues/19
                # Example:
                #   thread-ids={thread-id="1",thread-id="2"}
                # Results in:
                #   thread-ids: {{'thread-id': ['1', '2']}}
                # Rather than the lossy
                #   thread-ids: {'thread-id': 2}  # '1' got overwritten!
                if isinstance(obj[key], list):
                    obj[key].append(val)
                else:
                    obj[key] = [obj[key], val]
            else:
                obj[key] = val

            look_ahead_for_garbage = True
            c = stream.read(1)
            while look_ahead_for_garbage:
                if c in ["}", ",", ""]:
                    look_ahead_for_garbage = False
                else:
                    # got some garbage text, skip it. for example:
                    # name="gdb"gargage  # skip over 'garbage'
                    # name="gdb"\n  # skip over '\n'
                    if _DEBUG:
                        print("skipping unexpected charcter" + c)
                    c = stream.read(1)
            stream.seek(-1)

    if _DEBUG:
        print_green("parsed dict")
        print_green(obj)
    return obj
def _parse_array(to_parse):
    """Parse an array
    return (tuple):
        Number of characters parsed from to_parse
        Parsed array
    """
    if _DEBUG:
        print_red('array')
        print_red(to_parse)

    assert_match(_GDB_MI_CHAR_ARRAY_START, to_parse[0])

    # Skip first open bracket so we don't end up in an
    # endless loop trying to re-parse the array
    i = 1

    arr = []
    while i < len(to_parse) - 1:
        c = to_parse[i]

        if c in _GDB_MI_VALUE_START_CHARS:
            size, val = _parse_val(to_parse[i:])
            arr.append(val)
            i += size
        elif c in _WHITESPACE:
            pass
        elif c == ',':
            pass
        elif c == ']':
            # Stop when this array has finished. Note
            # that elements of this array can be also be arrays.
            break
        i += 1
    if _DEBUG:
        print_green(arr)
    return i, arr
Beispiel #11
0
def _parse_key_val(stream):
    """Parse key, value combination
    return (tuple):
        Parsed key (string)
        Parsed value (either a string, array, or dict)
    """

    if _DEBUG:
        print_green('parsing key/val')
    key = _parse_key(stream)
    val = _parse_val(stream)

    if _DEBUG:
        print_green('parsed key/val')
        print_green(key)
        print_green(val)
    return key, val
Beispiel #12
0
def _parse_key(stream):
    """Parse key, value combination
    returns :
        Parsed key (string)
    """
    if _DEBUG:
        print_green('parsing key')
    key = stream.advance_past_chars(['='])
    if _DEBUG:
        print_green('parsed key:')
        print_green(key)
    return key
Beispiel #13
0
def _parse_val(stream):
    """Parse value from string
    returns:
        Parsed value (either a string, array, or dict)
    """

    if _DEBUG:
        print_green("parsing value")

    while True:
        c = stream.read(1)

        if c == "{":
            # Start object
            val = _parse_dict(stream)
            break

        elif c == "[":
            # Start of an array
            val = _parse_array(stream)
            break

        elif c == '"':
            # Start of a string
            val = stream.advance_past_string_with_gdb_escapes()
            break

        elif _DEBUG:
            raise ValueError("unexpected character: %s" % c)

        else:
            print(
                'pygdbmi warning: encountered unexpected character: "%s". Continuing.'
                % c)
            val = ""  # this will be overwritten if there are more characters to be read

    if _DEBUG:
        print_green("parsed value:")
        print_green(val)

    return val