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 2009 Sun Microsystems, Inc. All rights reserved. 26# Use is subject to license terms. 27# 28 29# 30# Check that source files contain a valid comment block 31# 32 33import re, sys 34 35CmntChrs = r'#*!/\\";. ' 36 37class CmtBlkError(Exception): 38 def __init__(self, lineno, seen, shouldbe): 39 Exception.__init__(self) 40 self.lineno = lineno 41 self.seen = seen 42 self.shouldbe = shouldbe 43 44def checkblock(block, blk_text): 45 line = block['start'] 46 lictxt = block['block'] 47 48 for actual, valid in map(lambda x, y: (x and x.lstrip(CmntChrs), y), 49 lictxt, blk_text): 50 if actual != valid: 51 raise CmtBlkError(line, actual, valid) 52 line += 1 53 54def cmtblkchk(fh, blk_name, blk_text, filename=None, 55 lenient=False, verbose=False, output=sys.stderr): 56 57 ret = 0 58 blocks = [] 59 lic = [] 60 in_cmt = False 61 start = 0 62 lineno = 0 63 64 StartText = '%s HEADER START' % blk_name 65 EndText = '%s HEADER END' % blk_name 66 full_text = [StartText, ''] + blk_text + ['', EndText] 67 68 StartRE = re.compile(r'^[%s ]*%s' % (CmntChrs, StartText)) 69 EndRE = re.compile(r'^[%s ]*%s' % (CmntChrs, EndText)) 70 71 if not filename: 72 filename = fh.name 73 74 for line in fh: 75 line = line.rstrip('\r\n') 76 lineno += 1 77 78 if StartRE.search(line): 79 in_cmt = True 80 lic.append(line) 81 start = lineno 82 elif in_cmt and EndRE.search(line): 83 in_cmt = False 84 lic.append(line) 85 blocks.append({'start':start, 'block':lic}) 86 start = 0 87 lic = [] 88 elif in_cmt: 89 lic.append(line) 90 91 if in_cmt: 92 output.write('Error: Incomplete %s block in file %s\n' 93 ' at line %s\n''' % (blk_name, filename, start)) 94 95 # Check for no comment block, warn if we're not being lenient 96 if not len(blocks) and not lenient: 97 if not ret: 98 ret = 2 99 output.write("Warning: No %s block in file %s\n" % 100 (blk_name, filename)) 101 102 # Check for multiple comment blocks 103 if len(blocks) > 1: 104 ret = 1 105 output.write('Error: Multiple %s blocks in file %s\n' 106 ' at lines %s\n''' % 107 (blk_name, filename, 108 ', '.join([str(x['start']) for x in blocks]))) 109 110 # Validate each comment block 111 for b in blocks: 112 try: 113 checkblock(b, full_text) 114 except CmtBlkError, e: 115 ret = 1 116 output.write( 117 "Error: Invalid line in %s block in file %s\n" 118 " at line %d, should be\n" 119 " '%s'\n" 120 " is\n" 121 " '%s'\n" % (blk_name, filename, 122 e.lineno, e.shouldbe, e.seen)) 123 break 124 125 if verbose and not ret: 126 output.write("Message: Valid %s block in file %s\n" % 127 (blk_name, filename)) 128 129 return ret 130