xref: /illumos-gate/usr/src/tools/onbld/Checks/Cddl.py (revision b9ccdc5a)
1#! /usr/bin/python
2
3CDDL = '''
4CDDL HEADER START
5
6The contents of this file are subject to the terms of the
7Common Development and Distribution License (the "License").
8You may not use this file except in compliance with the License.
9
10You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11or http://www.opensolaris.org/os/licensing.
12See the License for the specific language governing permissions
13and limitations under the License.
14
15When distributing Covered Code, include this CDDL HEADER in each
16file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17If applicable, add the following below this CDDL HEADER, with the
18fields enclosed by brackets "[]" replaced with your own identifying
19information: Portions Copyright [yyyy] [name of copyright owner]
20
21CDDL HEADER END
22'''
23
24#
25# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
26# Use is subject to license terms.
27#
28# ident	"%Z%%M%	%I%	%E% SMI"
29#
30
31#
32# Check source files contain a valid CDDL block
33#
34
35import re, sys
36
37CDDL = CDDL.splitlines()[1:]		# Don't include initial \n
38
39CmntChrs = r'#*!/\\";. '
40CDDLStartRE = re.compile(r'^[%s ]*CDDL HEADER START' % CmntChrs)
41CDDLEndRE = re.compile(r'^[%s ]*CDDL HEADER END' % CmntChrs)
42
43class CddlError(Exception):
44	def __init__(self, lineno, seen, shouldbe):
45		Exception.__init__(self)
46		self.lineno = lineno
47		self.seen = seen
48		self.shouldbe = shouldbe
49
50def checkblock(block):
51	line = block['start']
52	lictxt = block['block']
53
54	for actual, valid in map(lambda x, y: (x and x.lstrip(CmntChrs), y),
55			       lictxt, CDDL):
56		if actual != valid:
57			raise CddlError(line, actual, valid)
58		line += 1
59
60def cddlchk(fh, filename=None, lenient=False, verbose=False, output=sys.stderr):
61	ret = 0
62	blocks = []
63	lic = []
64	in_cddl = False
65	start = 0
66	lineno = 0
67
68	if not filename:
69		filename = fh.name
70
71	for line in fh:
72		line = line.rstrip('\r\n')
73		lineno += 1
74
75		if CDDLStartRE.search(line):
76			in_cddl = True
77			lic.append(line)
78			start = lineno
79		elif in_cddl and CDDLEndRE.search(line):
80			in_cddl = False
81			lic.append(line)
82			blocks.append({'start':start, 'block':lic})
83			start = 0
84			lic = []
85		elif in_cddl:
86			lic.append(line)
87
88	if in_cddl:
89		output.write('Error: Incomplete CDDL block in file %s\n'
90			     '    at line %s\n''' % (filename, start))
91
92	# Check for no CDDL, warn if we're not being lenient
93	if not len(blocks) and not lenient:
94		if not ret:
95			ret = 2
96		output.write("Warning: No CDDL block in file %s\n" % filename)
97
98	# Check for multiple CDDL blocks
99	if len(blocks) > 1:
100		ret = 1
101		output.write('Error: Multiple CDDL blocks in file %s\n'
102			     '    at lines %s\n''' %
103			     (filename, ', '.join([str(x['start'])
104						   for x in blocks])))
105
106	# Validate each CDDL block
107	for b in blocks:
108		try:
109			checkblock(b)
110		except CddlError, e:
111			ret = 1
112			output.write(
113				"Error: Invalid line in CDDL block in file %s\n"
114				"    at line %d, should be\n"
115				"    '%s'\n"
116				"    is\n"
117				"    '%s'\n" % (filename, e.lineno,
118						e.shouldbe, e.seen))
119			break
120
121	if verbose and not ret:
122		output.write("Message: Valid CDDL block in file %s\n" %
123			     filename)
124
125	return ret
126