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