qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 17/44] qapi: Use returned bool to check for failure, Cocci


From: Vladimir Sementsov-Ogievskiy
Subject: Re: [PATCH v2 17/44] qapi: Use returned bool to check for failure, Coccinelle part
Date: Fri, 3 Jul 2020 17:56:09 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0

02.07.2020 18:49, Markus Armbruster wrote:
The previous commit enables conversion of

     visit_foo(..., &err);
     if (err) {
        ...
     }

to

     if (!visit_foo(..., errp)) {
        ...
     }

for visitor functions that now return true / false on success / error.
Coccinelle script:

     @@
     identifier fun =~ 
"check_list|input_type_enum|lv_start_struct|lv_type_bool|lv_type_int64|lv_type_str|lv_type_uint64|output_type_enum|parse_type_bool|parse_type_int64|parse_type_null|parse_type_number|parse_type_size|parse_type_str|parse_type_uint64|print_type_bool|print_type_int64|print_type_null|print_type_number|print_type_size|print_type_str|print_type_uint64|qapi_clone_start_alternate|qapi_clone_start_list|qapi_clone_start_struct|qapi_clone_type_bool|qapi_clone_type_int64|qapi_clone_type_null|qapi_clone_type_number|qapi_clone_type_str|qapi_clone_type_uint64|qapi_dealloc_start_list|qapi_dealloc_start_struct|qapi_dealloc_type_anything|qapi_dealloc_type_bool|qapi_dealloc_type_int64|qapi_dealloc_type_null|qapi_dealloc_type_number|qapi_dealloc_type_str|qapi_dealloc_type_uint64|qobject_input_check_list|qobject_input_check_struct|qobject_input_start_alternate|qobject_input_start_list|qobject_input_start_struct|qobject_input_type_any|qobject_input_type_bool|qobject_input_type_bool_keyval|qobject_input_type_int64|qobject_input_type_int64_keyval|qobject_input_type_null|qobject_input_type_number|qobject_input_type_number_keyval|qobject_input_type_size_keyval|qobject_input_type_str|qobject_input_type_str_keyval|qobject_input_type_uint64|qobject_input_type_uint64_keyval|qobject_output_start_list|qobject_output_start_struct|qobject_output_type_any|qobject_output_type_bool|qobject_output_type_int64|qobject_output_type_null|qobject_output_type_number|qobject_output_type_str|qobject_output_type_uint64|start_list|visit_check_list|visit_check_struct|visit_start_alternate|visit_start_list|visit_start_struct|visit_type_.*";
     expression list args;
     typedef Error;
     Error *err;
     @@
     -    fun(args, &err);
     -    if (err)
     +    if (!fun(args, &err))
          {
              ...
          }

A few line breaks tidied up manually.

Signed-off-by: Markus Armbruster<armbru@redhat.com>

Tha plain email contains "=20" instead of some whitespaces, which I don't like 
to parse with my script. So update the script to operate on git-show output from stdin:

#!/usr/bin/env python3

import sys
import re


re_remove_add = re.compile(r'(?P<remove>(^-.*\n)+)(?P<add>(^\+.*\n)+)',
                           flags=re.MULTILINE)
re_remove = re.compile(r'(?P<func_call>(?P<func>\w+)\(.*,&(?P<err>\w+)\));'
                       r'if\((?P=err)(!=NULL)?\)\{')
re_add = re.compile(r'if\(!(?P<func_call>.*)\)\{')
all_functions = set()


def check_subchunk(subchunk):
    """check subchunk

    Check that subchunk matches
        - func(args..., &err);
        - if (err) {
        + if (!func(args..., &err)) {
    ignoring indentation and spaces

    Also, while being here, register each found func in all_functions.
    """
    m = re_remove_add.fullmatch(subchunk)
    if not m:
        return False

    remove = re.sub(r'^-', '', m.group('remove'), flags=re.MULTILINE)
    remove = re.sub(r'\s', '', remove)

    add = re.sub(r'^\+', '', m.group('add'), flags=re.MULTILINE)
    add = re.sub(r'\s', '', add)

    m = re_remove.fullmatch(remove)
    if not m:
        return False

    all_functions.add(m.group('func'))
    func_call = m.group('func_call')

    m = re_add.fullmatch(add)

    if not m:
        return False

    return func_call == m.group('func_call')


if len(sys.argv) > 1:
    with open(sys.argv[1]) as f:
        patch = f.read()
else:
    patch = sys.stdin.read()

# Drop patch footer
patch = re.sub(r'^-- *\n(\d+\.)+\d+\s*\Z', '', patch, flags=re.MULTILINE)

files = re.split(r'(^diff .*\n'
                 r'^index .*\n'
                 r'^--- .*\n'
                 r'^\+\+\+ .*)\n', patch, flags=re.MULTILINE)

# Drop patch header
del files[0]

subchunk_re = re.compile(r'(^[+-].*\n)+', flags=re.MULTILINE)

all_ok = True
for i in range(0, len(files), 2):
    file = files[i]
    patch = files[i + 1]
    print_caption = True

    for chunk in re.split('^@', patch, flags=re.MULTILINE):
        if not all(check_subchunk(m.group(0))
                   for m in subchunk_re.finditer(chunk)):
            if print_caption:
                print(file)
                print_caption = False
            print(chunk)
            all_ok = False

if all_ok:
    print('ALL OK.\nfound functions:\n')
    print('\n'.join(list(all_functions)))

====
run it:
# git show | ../check2.py
ALL OK.
found functions:

visit_type_int64
visit_start_list
visit_type_int32
visit_type_bool
visit_type_uint8
visit_type_ThrottleLimits
visit_type_str
visit_start_struct
visit_type_int
visit_type_enum
visit_type_size
visit_type_uint16
visit_type_uint64
visit_type_SocketAddress
visit_type_uint32
visit_type_BlockPermissionList


Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>

--
Best regards,
Vladimir

reply via email to

[Prev in Thread] Current Thread [Next in Thread]