Annotation of embedaddon/rsync/packaging/var-checker, revision 1.1.1.2

1.1.1.2 ! misho       1: #!/usr/bin/env -S python3 -B
        !             2: 
1.1       misho       3: # This script checks the *.c files for extraneous "extern" variables,
                      4: # for vars that are defined but not used, and for inconsistent array
                      5: # sizes.  Run it from inside the main rsync directory.
                      6: 
1.1.1.2 ! misho       7: import re, argparse, glob
        !             8: 
        !             9: VARS_RE = re.compile(r'^(?!(?:extern|enum)\s)([a-zA-Z]\S*\s+.*);', re.M)
        !            10: EXTERNS_RE = re.compile(r'^extern\s+(.*);', re.M)
        !            11: 
        !            12: sizes = { }
        !            13: 
        !            14: def main():
        !            15:     add_syscall_c = set('t_stub.c t_unsafe.c tls.c trimslash.c'.split())
        !            16:     add_util_c = set('t_stub.c t_unsafe.c'.split())
        !            17: 
        !            18:     syscall_c = slurp_file('syscall.c', True)
        !            19:     util_c = slurp_file('util.c', True)
        !            20: 
        !            21:     for fn in sorted(glob.glob('*.c')):
        !            22:         txt = slurp_file(fn)
        !            23: 
        !            24:         var_list = parse_vars(fn, VARS_RE.findall(txt))
        !            25:         extern_list = parse_vars(fn, EXTERNS_RE.findall(txt))
        !            26:         if not var_list and not extern_list:
        !            27:             continue
        !            28: 
        !            29:         if fn in add_syscall_c:
        !            30:             txt += syscall_c
        !            31:         if fn in add_util_c:
        !            32:             txt += util_c
        !            33: 
        !            34:         txt = re.sub(r'INFO_GTE', 'info_levels ', txt)
        !            35:         txt = re.sub(r'DEBUG_GTE', 'debug_levels ', txt)
        !            36:         txt = re.sub(r'SIGACTION\(', 'sigact (', txt)
        !            37: 
        !            38:         find = '|'.join([ re.escape(x) for x in var_list + extern_list ])
        !            39:         var_re = re.compile(r'(?<!\sstruct )\b(%s)(?!\w)' % find)
        !            40: 
        !            41:         found = { x: 0 for x in var_list + extern_list }
        !            42:         for var in var_re.findall(txt):
        !            43:             found[var] += 1
        !            44: 
        !            45:         for var in sorted(var_list + extern_list):
        !            46:             if found[var] == 1:
        !            47:                 vtype = 'var' if var in var_list else 'extern'
        !            48:                 print(fn, f'has extraneous {vtype}: "{var}"')
        !            49: 
        !            50: 
        !            51: def slurp_file(fn, drop_externs=False):
        !            52:     with open(fn, 'r', encoding='utf-8') as fh:
        !            53:         txt = fh.read()
        !            54:     if drop_externs:
        !            55:         txt = EXTERNS_RE.sub('', txt)
        !            56:     return txt
        !            57: 
        !            58: 
        !            59: def parse_vars(fn, lines):
        !            60:     ret = [ ]
        !            61:     for line in lines:
        !            62:         line = re.sub(r'\s*\{.*\}', '', line)
        !            63:         line = re.sub(r'\s*\(.*\)', '', line)
        !            64:         for item in re.split(r'\s*,\s*', line):
        !            65:             item = re.sub(r'\s*=.*', '', item)
        !            66:             m = re.search(r'(?P<var>\w+)(?P<sz>\[.*?\])?$', item)
        !            67:             if not m:
        !            68:                 print(f"Bogus match? ({item})")
        !            69:                 continue
        !            70:             if m['sz']:
        !            71:                 if m['var'] in sizes:
        !            72:                     if sizes[m['var']] != m['sz']:
        !            73:                         var = m['var']
        !            74:                         print(fn, f'has inconsistent size for "{var}":', m['sz'], 'vs', sizes[var])
        !            75:                 else:
        !            76:                     sizes[m['var']] = m['sz']
        !            77:             ret.append(m['var'])
        !            78:     return ret
        !            79: 
        !            80: 
        !            81: if __name__ == '__main__':
        !            82:     parser = argparse.ArgumentParser(description='Check the *.c files for extraneous extern vars.', add_help=False)
        !            83:     parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.")
        !            84:     args = parser.parse_args()
        !            85:     main()
1.1       misho      86: 
1.1.1.2 ! misho      87: # vim: sw=4 et ft=python

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>