]>
git.proxmox.com Git - ovs.git/blob - build-aux/extract-ofp-errors
11 idRe
= "[a-zA-Z_][a-zA-Z_0-9]*"
12 tokenRe
= "#?" + idRe
+ "|[0-9]+|."
19 line
= inputFile
.readline()
22 fatal("unexpected end of input")
32 if line
.startswith("/*"):
36 commentEnd
= line
.find("*/")
41 line
= line
[commentEnd
+ 2:]
43 match
= re
.match(tokenRe
, line
)
44 token
= match
.group(0)
45 line
= line
[len(token
):]
46 if token
.startswith('#'):
48 elif token
in macros
and not inDirective
:
49 line
= macros
[token
] + line
58 line
= inputFile
.readline()
60 while line
.endswith("\\\n"):
61 line
= line
[:-2] + inputFile
.readline()
65 fatal("unexpected end of input")
72 sys
.stderr
.write("%s:%d: %s\n" % (fileName
, lineNumber
, msg
))
85 return re
.match(idRe
+ "$", s
) != None
89 fatal("identifier expected")
92 if not re
.match('[0-9]+$', token
):
93 fatal("integer expected")
104 fatal("%s expected" % t
)
106 def parseTaggedName():
107 assert token
in ('struct', 'union')
111 name
= "%s %s" % (name
, token
)
115 def print_enum(tag
, constants
, storage_class
):
117 %(storage_class)sconst char *
118 %(tag)s_to_string(uint16_t value)
122 "bufferlen": len(tag
) + 32,
123 "storage_class": storage_class
}
124 for constant
in constants
:
125 print " case %s: return \"%s\";" % (constant
, constant
)
133 argv0
= os
.path
.basename(sys
.argv
[0])
135 %(argv0)s, for extracting OpenFlow error codes from header files
136 usage: %(argv0)s FILE [FILE...]
138 This program reads the header files specified on the command line and
139 outputs a C source file for translating OpenFlow error codes into
140 strings, for use as lib/ofp-errors.c in the Open vSwitch source tree.
142 This program is specialized for reading lib/ofp-errors.h. It will not
143 work on arbitrary header files without extensions.\
144 ''' % {"argv0": argv0
}
147 def extract_ofp_errors(filenames
):
154 for domain_name
in ("OF1.0", "OF1.1", "OF1.2", "NX1.0", "NX1.1"):
155 domain
[domain_name
] = {}
156 reverse
[domain_name
] = {}
162 for fileName
in filenames
:
165 inputFile
= open(fileName
)
170 if re
.match('enum ofperr', line
):
175 if line
.startswith('/*') or not line
or line
.isspace():
177 elif re
.match('}', line
):
180 if not line
.lstrip().startswith('/*'):
181 fatal("unexpected syntax between errors")
183 comment
= line
.lstrip()[2:].strip()
184 while not comment
.endswith('*/'):
186 if line
.startswith('/*') or not line
or line
.isspace():
187 fatal("unexpected syntax within error")
188 comment
+= ' %s' % line
.lstrip('* \t').rstrip(' \t\r\n')
189 comment
= comment
[:-2].rstrip()
191 m
= re
.match('Expected: (.*)\.$', comment
)
193 expected_errors
[m
.group(1)] = (fileName
, lineNumber
)
196 m
= re
.match('((?:.(?!\. ))+.)\. (.*)$', comment
)
198 fatal("unexpected syntax between errors")
200 dsts
, comment
= m
.groups()
203 m
= re
.match('\s+(?:OFPERR_((?:OFP|NX)[A-Z0-9_]+))(\s*=\s*OFPERR_OFS)?,',
206 fatal("syntax error expecting enum value")
210 comments
.append(re
.sub('\[[^]]*\]', '', comment
))
213 for dst
in dsts
.split(', '):
214 m
= re
.match(r
'([A-Z0-9.+]+)\((\d+|(0x)[0-9a-fA-F]+)(?:,(\d+))?\)$', dst
)
216 fatal("%s: syntax error in destination" % dst
)
222 type_
= int(m
.group(2), base
)
224 code
= int(m
.group(4))
228 target_map
= {"OF1.0+": ("OF1.0", "OF1.1", "OF1.2"),
229 "OF1.1+": ("OF1.1", "OF1.2"),
230 "OF1.2+": ("OF1.2",),
234 "NX1.0+": ("OF1.0", "OF1.1", "OF1.2"),
237 "NX1.1+": ("OF1.1",),
239 if targets
not in target_map
:
240 fatal("%s: unknown error domain" % targets
)
241 for target
in target_map
[targets
]:
242 domain
[target
].setdefault(type_
, {})
243 if code
in domain
[target
][type_
]:
244 msg
= "%d,%d in %s means both %s and %s" % (
246 domain
[target
][type_
][code
][0], enum
)
247 if msg
in expected_errors
:
248 del expected_errors
[msg
]
250 error("%s: %s." % (dst
, msg
))
251 sys
.stderr
.write("%s:%d: %s: Here is the location "
252 "of the previous definition.\n"
253 % (domain
[target
][type_
][code
][1],
254 domain
[target
][type_
][code
][2],
257 domain
[target
][type_
][code
] = (enum
, fileName
,
260 if enum
in reverse
[target
]:
261 error("%s: %s in %s means both %d,%d and %d,%d." %
263 reverse
[target
][enum
][0],
264 reverse
[target
][enum
][1],
266 reverse
[target
][enum
] = (type_
, code
)
270 for fn
, ln
in expected_errors
.itervalues():
271 sys
.stderr
.write("%s:%d: expected duplicate not used.\n" % (fn
, ln
))
278 /* Generated automatically; do not modify! -*- buffer-read-only: t -*- */
280 #define OFPERR_N_ERRORS %d
282 struct ofperr_domain {
285 enum ofperr (*decode)(uint16_t type, uint16_t code);
286 enum ofperr (*decode_type)(uint16_t type);
287 struct pair errors[OFPERR_N_ERRORS];
290 static const char *error_names[OFPERR_N_ERRORS] = {
294 static const char *error_comments[OFPERR_N_ERRORS] = {
298 '\n'.join(' "%s",' % name
for name
in names
),
299 '\n'.join(' "%s",' % re
.sub(r
'(["\\])', r
'\\\1', comment
)
300 for comment
in comments
))
302 def output_domain(map, name
, description
, version
):
305 %s_decode(uint16_t type, uint16_t code)
307 switch ((type << 16) | code) {""" % name
312 type_
, code
= map[enum
]
315 value
= (type_
<< 16) | code
319 print " case (%d << 16) | %d:" % (type_
, code
)
320 print " return OFPERR_%s;" % enum
328 %s_decode_type(uint16_t type)
330 switch (type) {""" % name
334 type_
, code
= map[enum
]
337 print " case %d:" % type_
338 print " return OFPERR_%s;" % enum
346 static const struct ofperr_domain %s = {
351 {""" % (name
, description
, version
, name
, name
)
354 type_
, code
= map[enum
]
359 print " { %2d, %3d }, /* %s */" % (type_
, code
, enum
)
364 output_domain(reverse
["OF1.0"], "ofperr_of10", "OpenFlow 1.0", 0x01)
365 output_domain(reverse
["OF1.1"], "ofperr_of11", "OpenFlow 1.1", 0x02)
366 output_domain(reverse
["OF1.2"], "ofperr_of12", "OpenFlow 1.2", 0x03)
368 if __name__
== '__main__':
369 if '--help' in sys
.argv
:
371 elif len(sys
.argv
) < 2:
372 sys
.stderr
.write("at least one non-option argument required; "
373 "use --help for help\n")
376 extract_ofp_errors(sys
.argv
[1:])