buildtools: make experimental symbol check lighter
[dpdk.git] / devtools / check-symbol-change.sh
1 #!/bin/sh
2 # SPDX-License-Identifier: BSD-3-Clause
3 # Copyright(c) 2018 Neil Horman <nhorman@tuxdriver.com>
4
5 build_map_changes()
6 {
7         local fname="$1"
8         local mapdb="$2"
9
10         cat "$fname" | awk '
11                 # Initialize our variables
12                 BEGIN {map="";sym="";ar="";sec=""; in_sec=0; in_map=0}
13
14                 # Anything that starts with + or -, followed by an a
15                 # and ends in the string .map is the name of our map file
16                 # This may appear multiple times in a patch if multiple
17                 # map files are altered, and all section/symbol names
18                 # appearing between a triggering of this rule and the
19                 # next trigger of this rule are associated with this file
20                 /[-+] a\/.*\.map/ {map=$2; in_map=1}
21
22                 # Same pattern as above, only it matches on anything that
23                 # does not end in 'map', indicating we have left the map chunk.
24                 # When we hit this, turn off the in_map variable, which
25                 # supresses the subordonate rules below
26                 /[-+] a\/.*\.[^map]/ {in_map=0}
27
28                 # Triggering this rule, which starts a line and ends it
29                 # with a { identifies a versioned section.  The section name is
30                 # the rest of the line with the + and { symbols remvoed.
31                 # Triggering this rule sets in_sec to 1, which actives the
32                 # symbol rule below
33                 /^.*{/ {
34                         gsub("+", "");
35                         if (in_map == 1) {
36                                 sec=$(NF-1); in_sec=1;
37                         }
38                 }
39
40                 # This rule idenfies the end of a section, and disables the
41                 # symbol rule
42                 /.*}/ {in_sec=0}
43
44                 # This rule matches on a + followed by any characters except a :
45                 # (which denotes a global vs local segment), and ends with a ;.
46                 # The semicolon is removed and the symbol is printed with its
47                 # association file name and version section, along with an
48                 # indicator that the symbol is a new addition.  Note this rule
49                 # only works if we have found a version section in the rule
50                 # above (hence the in_sec check) And found a map file (the
51                 # in_map check).  If we are not in a map chunk, do nothing.  If
52                 # we are in a map chunk but not a section chunk, record it as
53                 # unknown.
54                 /^+[^}].*[^:*];/ {gsub(";","");sym=$2;
55                         if (in_map == 1) {
56                                 if (in_sec == 1) {
57                                         print map " " sym " " sec " add"
58                                 } else {
59                                         print map " " sym " unknown add"
60                                 }
61                         }
62                 }
63
64                 # This is the same rule as above, but the rule matches on a
65                 # leading - rather than a +, denoting that the symbol is being
66                 # removed.
67                 /^-[^}].*[^:*];/ {gsub(";","");sym=$2;
68                         if (in_map == 1) {
69                                 if (in_sec == 1) {
70                                         print map " " sym " " sec " del"
71                                 } else {
72                                         print map " " sym " unknown del"
73                                 }
74                         }
75                 }' > "$mapdb"
76
77                 sort -u "$mapdb" > "$mapdb.2"
78                 mv -f "$mapdb.2" "$mapdb"
79
80 }
81
82 check_for_rule_violations()
83 {
84         local mapdb="$1"
85         local mname
86         local symname
87         local secname
88         local ar
89         local ret=0
90
91         while read mname symname secname ar
92         do
93                 if [ "$ar" = "add" ]
94                 then
95
96                         if [ "$secname" = "unknown" ]
97                         then
98                                 # Just inform the user of this occurrence, but
99                                 # don't flag it as an error
100                                 echo -n "INFO: symbol $symname is added but "
101                                 echo -n "patch has insuficient context "
102                                 echo -n "to determine the section name "
103                                 echo -n "please ensure the version is "
104                                 echo "EXPERIMENTAL"
105                                 continue
106                         fi
107
108                         oldsecname=$(sed -n \
109                         "s#$mname $symname \(.*\) del#\1#p" "$mapdb")
110
111                         # A symbol can not enter a non experimental
112                         # section directly
113                         if [ -z "$oldsecname" ]
114                         then
115                                 if [ "$secname" = 'EXPERIMENTAL' ]
116                                 then
117                                         echo -n "INFO: symbol $symname has "
118                                         echo -n "been added to the "
119                                         echo -n "EXPERIMENTAL section of the "
120                                         echo "version map"
121                                         continue
122                                 else
123                                         echo -n "ERROR: symbol $symname "
124                                         echo -n "is added in the $secname "
125                                         echo -n "section, but is expected to "
126                                         echo -n "be added in the EXPERIMENTAL "
127                                         echo "section of the version map"
128                                         ret=1
129                                         continue
130                                 fi
131                         fi
132
133                         # This symbol is moving inside a section, nothing to do
134                         if [ "$oldsecname" = "$secname" ]
135                         then
136                                 continue
137                         fi
138
139                         # This symbol is moving between two sections (the
140                         # original section is not experimental).
141                         # This can be legit, just warn.
142                         if [ "$oldsecname" != 'EXPERIMENTAL' ]
143                         then
144                                 echo -n "INFO: symbol $symname is being "
145                                 echo -n "moved from $oldsecname to $secname. "
146                                 echo -n "Ensure that it has gone through the "
147                                 echo "deprecation process"
148                                 continue
149                         fi
150                 else
151
152                         if ! grep -q "$mname $symname .* add" "$mapdb" && \
153                            [ "$secname" != "EXPERIMENTAL" ]
154                         then
155                                 # Just inform users that non-experimenal
156                                 # symbols need to go through a deprecation
157                                 # process
158                                 echo -n "INFO: symbol $symname is being "
159                                 echo -n "removed, ensure that it has "
160                                 echo "gone through the deprecation process"
161                         fi
162                 fi
163         done < "$mapdb"
164
165         return $ret
166 }
167
168 trap clean_and_exit_on_sig EXIT
169
170 mapfile=`mktemp -t dpdk.mapdb.XXXXXX`
171 patch=$1
172 exit_code=1
173
174 clean_and_exit_on_sig()
175 {
176         rm -f "$mapfile"
177         exit $exit_code
178 }
179
180 build_map_changes "$patch" "$mapfile"
181 check_for_rule_violations "$mapfile"
182 exit_code=$?
183 rm -f "$mapfile"
184
185 exit $exit_code