summaryrefslogtreecommitdiff
path: root/usr/src/tools/onbld/Checks/CmtBlk.py
blob: ddf5caec48782eb25db463339ed0ad8d0174ff66 (plain)
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
124
125
126
127
128
#!ON_PYTHON

#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#

#
# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
#

#
# Check that source files contain a valid comment block
#

import re, sys

CmntChrs = r'#*!/\\";. '

class CmtBlkError(Exception):
	def __init__(self, lineno, seen, shouldbe):
		Exception.__init__(self)
		self.lineno = lineno
		self.seen = seen
		self.shouldbe = shouldbe

def checkblock(block, blk_text):
	line = block['start']
	lictxt = block['block']

	for actual, valid in map(lambda x, y: (x and x.lstrip(CmntChrs), y),
			       lictxt, blk_text):
		if actual != valid:
			raise CmtBlkError(line, actual, valid)
		line += 1

def cmtblkchk(fh, blk_name, blk_text, filename=None,
	      lenient=False, verbose=False, output=sys.stderr):

	ret = 0
	blocks = []
	lic = []
	in_cmt = False
	start = 0
	lineno = 0

	StartText = '%s HEADER START' % blk_name
	EndText = '%s HEADER END' % blk_name
	full_text = [StartText, ''] + blk_text + ['', EndText]

	StartRE = re.compile(r'^[%s ]*%s' % (CmntChrs, StartText))
	EndRE = re.compile(r'^[%s ]*%s' % (CmntChrs, EndText))

	if not filename:
		filename = fh.name

	for line in fh:
		line = line.rstrip('\r\n')
		lineno += 1
		
		if StartRE.search(line):
			in_cmt = True
			lic.append(line)
			start = lineno
		elif in_cmt and EndRE.search(line):
			in_cmt = False
			lic.append(line)
			blocks.append({'start':start, 'block':lic})
			start = 0
			lic = []
		elif in_cmt:
			lic.append(line)

	if in_cmt:
		output.write('%s: %s: Error: Incomplete %s block\n''' %
		    (filename, start, blk_name))

	# Check for no comment block, warn if we're not being lenient
	if not len(blocks) and not lenient:
		if not ret:
			ret = 2
		output.write("%s: Warning: No %s block\n" %
			     (filename, blk_name))

	# Check for multiple comment blocks
	if len(blocks) > 1:
		ret = 1
		output.write('%s: Error: Multiple %s blocks\n'
			     '    at lines %s\n''' %
			     (filename, blk_name,
			      ', '.join([str(x['start']) for x in blocks])))

	# Validate each comment block
	for b in blocks:
		try:
			checkblock(b, full_text)
		except CmtBlkError, e:
			ret = 1
			output.write(
				"%s: %d: Error: Invalid line in %s block:\n"
				"    should be\n"
				"    '%s'\n"
				"    is\n"
				"    '%s'\n" % (filename, e.lineno, blk_name,
						e.shouldbe, e.seen))
			break
		
	if verbose and not ret:
		output.write("%s: Valid %s block\n" %
			     (filename, blk_name))

	return ret