Cddl.py revision cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0
fa9e4066f08beec538e775443c5be79dd423fcabahrens#! /usr/bin/python
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensCDDL = '''
fa9e4066f08beec538e775443c5be79dd423fcabahrensCDDL HEADER START
441d80aa4f613b6298fc8bd3151f4be02dbf84fclling
441d80aa4f613b6298fc8bd3151f4be02dbf84fcllingThe contents of this file are subject to the terms of the
fa9e4066f08beec538e775443c5be79dd423fcabahrensCommon Development and Distribution License (the "License").
fa9e4066f08beec538e775443c5be79dd423fcabahrensYou may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensYou can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrensor http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrensSee the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrensand limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensWhen distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrensfile and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrensIf applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrensfields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrensinformation: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens
99653d4ee642c6528e88224f12409a5f23060994eschrockCDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens'''
379c004d1f26b343f034bba8a350290691d00d38Eric Schrock
fa9e4066f08beec538e775443c5be79dd423fcabahrens#
fa9e4066f08beec538e775443c5be79dd423fcabahrens# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens# Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens#
fa9e4066f08beec538e775443c5be79dd423fcabahrens# ident "%Z%%M% %I% %E% SMI"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#
fa9e4066f08beec538e775443c5be79dd423fcabahrens# Check source files contain a valid CDDL block
fa9e4066f08beec538e775443c5be79dd423fcabahrens#
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensimport re, sys
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensCDDL = CDDL.splitlines()[1:] # Don't include initial \n
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensCmntChrs = r'#*!/\\";. '
fa9e4066f08beec538e775443c5be79dd423fcabahrensCDDLStartRE = re.compile(r'^[%s ]*CDDL HEADER START' % CmntChrs)
fa9e4066f08beec538e775443c5be79dd423fcabahrensCDDLEndRE = re.compile(r'^[%s ]*CDDL HEADER END' % CmntChrs)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarksclass CddlError(Exception):
b1b8ab34de515a5e83206da22c3d7e563241b021lling def __init__(self, lineno, seen, shouldbe):
fa9e4066f08beec538e775443c5be79dd423fcabahrens Exception.__init__(self)
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.lineno = lineno
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.seen = seen
fa9e4066f08beec538e775443c5be79dd423fcabahrens self.shouldbe = shouldbe
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensdef checkblock(block):
b7b97454b9b1f6625e7e655e9651e744a8dee09dperrin line = block['start']
fa9e4066f08beec538e775443c5be79dd423fcabahrens lictxt = block['block']
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for actual, valid in map(lambda x, y: (x and x.lstrip(CmntChrs), y),
fa9e4066f08beec538e775443c5be79dd423fcabahrens lictxt, CDDL):
fa9e4066f08beec538e775443c5be79dd423fcabahrens if actual != valid:
99653d4ee642c6528e88224f12409a5f23060994eschrock raise CddlError(line, actual, valid)
fa9e4066f08beec538e775443c5be79dd423fcabahrens line += 1
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensdef cddlchk(fh, filename=None, lenient=False, verbose=False, output=sys.stderr):
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 0
fa9e4066f08beec538e775443c5be79dd423fcabahrens blocks = []
fa9e4066f08beec538e775443c5be79dd423fcabahrens lic = []
fa9e4066f08beec538e775443c5be79dd423fcabahrens in_cddl = False
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock start = 0
fa9e4066f08beec538e775443c5be79dd423fcabahrens lineno = 0
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if not filename:
fa9e4066f08beec538e775443c5be79dd423fcabahrens filename = fh.name
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens for line in fh:
fa9e4066f08beec538e775443c5be79dd423fcabahrens line = line.rstrip('\r\n')
fa9e4066f08beec538e775443c5be79dd423fcabahrens lineno += 1
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if CDDLStartRE.search(line):
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock in_cddl = True
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock lic.append(line)
06eeb2ad640ce72d394ac521094bed7681044408ek start = lineno
06eeb2ad640ce72d394ac521094bed7681044408ek elif in_cddl and CDDLEndRE.search(line):
b1b8ab34de515a5e83206da22c3d7e563241b021lling in_cddl = False
b1b8ab34de515a5e83206da22c3d7e563241b021lling lic.append(line)
b1b8ab34de515a5e83206da22c3d7e563241b021lling blocks.append({'start':start, 'block':lic})
fa9e4066f08beec538e775443c5be79dd423fcabahrens start = 0
fa9e4066f08beec538e775443c5be79dd423fcabahrens lic = []
fa9e4066f08beec538e775443c5be79dd423fcabahrens elif in_cddl:
fa9e4066f08beec538e775443c5be79dd423fcabahrens lic.append(line)
29ab75c9a733dad2978c4860efd954b5625e3467rm
29ab75c9a733dad2978c4860efd954b5625e3467rm if in_cddl:
fa9e4066f08beec538e775443c5be79dd423fcabahrens output.write('Error: Incomplete CDDL block in file %s\n'
99653d4ee642c6528e88224f12409a5f23060994eschrock ' at line %s\n''' % (filename, start))
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens # Check for no CDDL, warn if we're not being lenient
fa9e4066f08beec538e775443c5be79dd423fcabahrens if not len(blocks) and not lenient:
fa9e4066f08beec538e775443c5be79dd423fcabahrens if not ret:
fa9e4066f08beec538e775443c5be79dd423fcabahrens ret = 2
fa9e4066f08beec538e775443c5be79dd423fcabahrens output.write("Warning: No CDDL block in file %s\n" % filename)
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens # Check for multiple CDDL blocks
fa9e4066f08beec538e775443c5be79dd423fcabahrens if len(blocks) > 1:
29ab75c9a733dad2978c4860efd954b5625e3467rm ret = 1
fa9e4066f08beec538e775443c5be79dd423fcabahrens output.write('Error: Multiple CDDL blocks in file %s\n'
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock ' at lines %s\n''' %
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock (filename, ', '.join([str(x['start'])
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock for x in blocks])))
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock # Validate each CDDL block
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock for b in blocks:
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock try:
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock checkblock(b)
06eeb2ad640ce72d394ac521094bed7681044408ek except CddlError, e:
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock ret = 1
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock output.write(
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock "Error: Invalid line in CDDL block in file %s\n"
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock " at line %d, should be\n"
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock " '%s'\n"
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock " is\n"
99653d4ee642c6528e88224f12409a5f23060994eschrock " '%s'\n" % (filename, e.lineno,
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock e.shouldbe, e.seen))
eaca9bbd5f5d1e4e554da4c7108e8a03c8c33481eschrock break
b1b8ab34de515a5e83206da22c3d7e563241b021lling
b1b8ab34de515a5e83206da22c3d7e563241b021lling if verbose and not ret:
b1b8ab34de515a5e83206da22c3d7e563241b021lling output.write("Message: Valid CDDL block in file %s\n" %
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock filename)
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock
65cd9f2809a015b46790a9c5c2ef992d56177624eschrock return ret
fa9e4066f08beec538e775443c5be79dd423fcabahrens