File: parse-glibc.py

package info (click to toggle)
cppcheck 2.18.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 26,132 kB
  • sloc: cpp: 268,935; python: 20,890; ansic: 8,090; sh: 1,045; makefile: 1,008; xml: 1,005; cs: 291
file content (123 lines) | stat: -rw-r--r-- 3,685 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3

import glob
import os


def checknonnull(cfg, functionName, nonnull):
    pos1 = cfg.find('<function name="' + functionName + '">')
    if pos1 < 0:
        return
    pos2 = cfg.find('</function>', pos1)
    if pos2 < 0:
        return
    functionCfg = cfg[pos1:pos2]
    s = None
    for argnr in range(10):
        argpos1 = functionCfg.find('<arg nr="' + str(argnr) + '">')
        if argpos1 < 0:
            continue
        argpos2 = functionCfg.find('</arg>', argpos1)
        notnullpos = functionCfg.find('not-null', argpos1)
        if 0 <= notnullpos < argpos2:
            if s:
                s += ', ' + str(argnr)
            else:
                s = str(argnr)
    if s != nonnull:
        if not nonnull:
            nonnull = ''
        if not s:
            s = ''
        print(functionName + '\tglibc:' + nonnull + '\tcfg:' + s)


def parseheader(cppcheckpath, filename):
    with open(filename, 'rt') as f:
        data = f.read()

    with open(cppcheckpath + '/cfg/std.cfg', 'rt') as f:
        stdcfg = f.read()

    with open(cppcheckpath + '/cfg/posix.cfg', 'rt') as f:
        posixcfg = f.read()

    while '/*' in data:
        pos1 = data.find('/*')
        pos2 = data.find('*/', pos1 + 2)
        data = data[:pos1] + data[pos2 + 2:]

    data = data.replace('\\\n', '')

    while '\n#' in data:
        pos1 = data.find('\n#')
        pos2 = data.find('\n', pos1 + 1)
        data = data[:pos1] + data[pos2:]

    while '\n__BEGIN' in data:
        pos1 = data.find('\n__BEGIN')
        pos2 = data.find('\n', pos1 + 1)
        data = data[:pos1] + data[pos2:]

    while '\n__END' in data:
        pos1 = data.find('\n__END')
        pos2 = data.find('\n', pos1 + 1)
        data = data[:pos1] + data[pos2:]

    data = data.replace('\n\n', '\n')
    data = data.replace('\t', '    ')
    data = data.replace(',\n  ', ',')
    data = data.replace(')\n  ', ',')
    data = data.replace('  ', ' ')

    output = []

    for line in data.split('\n'):
        if (line[:7] != 'extern ' and ' extern ' not in line) or line[-1] != ';':
            continue

        functionNameEnd = line.find('(') - 1
        if functionNameEnd < 0:
            continue
        while line[functionNameEnd] == ' ':
            functionNameEnd -= 1
        if functionNameEnd < 10:
            continue
        functionNameStart = functionNameEnd
        while line[functionNameStart] == '_' or line[functionNameStart].isalnum():
            functionNameStart -= 1
        if functionNameStart < 10:
            continue
        if line[functionNameStart] != '*' and line[functionNameStart] != ' ':
            continue
        functionNameStart += 1
        if not line[functionNameStart].isalpha():
            continue

        functionName = line[functionNameStart:functionNameEnd + 1]

        nonnull = None

        nonnullStart = line.find('__nonnull')
        if nonnullStart >= 0:
            nonnullStart += 9
            while nonnullStart < len(line) and line[nonnullStart] == ' ':
                nonnullStart += 1
            if nonnullStart >= len(line) or line[nonnullStart] != '(':
                continue
            while line[nonnullStart] == '(':
                nonnullStart += 1
            nonnullEnd = line.find(')', nonnullStart)
            nonnull = line[nonnullStart:nonnullEnd]

        checknonnull(stdcfg, functionName, nonnull)
        checknonnull(posixcfg, functionName, nonnull)

        if nonnull:
            s = functionName + ' ' + nonnull
            if s not in output:
                output.append(s)


for f in glob.glob('/usr/include/*.h'):
    parseheader(os.path.expanduser('~/cppcheck'), f)