cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER START
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# The contents of this file are subject to the terms of the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Common Development and Distribution License (the "License").
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You may not use this file except in compliance with the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# See the License for the specific language governing permissions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# and limitations under the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# When distributing Covered Code, include this CDDL HEADER in each
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# If applicable, add the following below this CDDL HEADER, with the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# fields enclosed by brackets "[]" replaced with your own identifying
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# information: Portions Copyright [yyyy] [name of copyright owner]
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER END
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Use is subject to license terms.
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# Copyright 2008, 2010, Richard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Check that header files conform to our standards
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Standards for all header files (lenient):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 1) Begin with a comment containing a copyright message
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 2) Enclosed in a guard of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifndef GUARD
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #define GUARD
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #endif /* [!]GUARD */
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# The preferred form is without the bang character, but either is
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# acceptable.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 3) Has a valid ident declaration
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Additional standards for system header files:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 1) The file guard must take the form '_FILENAME_H[_]', where FILENAME
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# matches the basename of the file. If it is installed in a
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# subdirectory, it must be of the form _DIR_FILENAME_H. The form
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# without the trailing underscore is preferred.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 2) All #include directives must use the <> form.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 3) If the header file contains anything besides comments and
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# preprocessor directives, then it must be enclosed in a C++ guard of
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# extern "C" {
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def __init__(self, fh, filename=None, lenient=False):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Recursively join continuation lines
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Optionally take a line to start skipping/processing with
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # When lenient, allow C++ comments
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # We explicitly exclude the form used in the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # CDDL header rather than attempting to craft
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # a match for every possibly valid copyright
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Keyword strings (both expanded and literal) for the various SCMs
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Be certain to wrap each full expression in parens.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson r'((\%Z\%(\%M\%)\t\%I\%|\%W\%)\t\%E\% SMI)',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson r'(@\(#\)(\w[-\.\w]+\.h)\t\d+\.\d+(\.\d+\.\d+)?\t\d\d/\d\d/\d\d SMI)',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsondef hdrchk(fh, filename=None, lenient=False, output=sys.stderr):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson hdr = HeaderFile(fh, filename=filename, lenient=lenient)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Headers must begin with a comment containing a copyright notice. We
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # don't validate the contents of the copyright, only that it exists
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing copyright in opening comment", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # For application header files only, allow the ident string to appear
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # before the header guard.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if lenient and line.startswith("#pragma ident") and IDENT.search(line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 3: Header guards
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match = re.search(r'^#ifndef\s([a-zA-Z0-9_]+)$', line)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Invalid or missing header guard", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # If we aren't being lenient, validate the name of the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guardname = guardname.replace('.', '_').replace('-','_')
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not re.search(r'^_.*%s[_]?$' % guardname, guard):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 4: ident string
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # We allow both the keyword and extracted versions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if (not found_ident and line.startswith("#pragma ident") and
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Main processing loop
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not (line.startswith('#') or line.startswith('using')):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # For system files, make sure #includes are of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # '#include <file>'
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif not in_cplusplus and re.search(r'^#ifdef\s__cplusplus$',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Start of C++ header guard.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Make sure it is of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # extern "C" {
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif in_cplusplus and re.search(r'^#ifdef\s__cplusplus$', line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # End of C++ header guard. Make sure it is of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif re.search(r'^#endif\s/\* [!]?%s \*/$' % guard, line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Ending header guard
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Check for missing end clauses
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if (not lenient) and (not found_cplusplus) and found_code:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing closing #ifdef __cplusplus", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing or invalid ending header guard", hdr)