cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#! /usr/bin/python
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER START
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
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#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# or http://www.opensolaris.org/os/licensing.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# See the License for the specific language governing permissions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# and limitations under the License.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
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#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# CDDL HEADER END
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Use is subject to license terms.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe# Copyright 2008, 2010, Richard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Check that header files conform to our standards
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Standards for all header files (lenient):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 1) Begin with a comment containing a copyright message
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 2) Enclosed in a guard of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifndef GUARD
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #define GUARD
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #endif /* [!]GUARD */
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# The preferred form is without the bang character, but either is
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# acceptable.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 3) Has a valid ident declaration
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Additional standards for system header files:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
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#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# 2) All #include directives must use the <> form.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
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# the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# extern "C" {
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #endif
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# }
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# #endif
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonimport re, os, sys
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowefrom onbld.Checks.Copyright import is_copyright
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonclass HeaderFile(object):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def __init__(self, fh, filename=None, lenient=False):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.file = fh
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.lenient = lenient
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.lineno = 0
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.has_copyright = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.eof = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if filename:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.filename = filename
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.filename = fh.name
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def getline(self):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson for line in self.file:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.lineno += 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not line or line.isspace():
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = line.rstrip('\r\n')
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Recursively join continuation lines
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if line.endswith('\\'):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = line[0:-1] + self.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return line
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.eof = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return ''
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Optionally take a line to start skipping/processing with
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson def skipcomments(self, curline=None):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = curline or self.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson while line:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # When lenient, allow C++ comments
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if self.lenient and re.search(r'^\s*//', line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = self.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not re.search(r'^\s*/\*', line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return line
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson while not re.search(r'\*/', line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
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 # notice
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe if is_copyright(line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.has_copyright = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = self.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe if is_copyright(line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson self.has_copyright = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = self.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return line
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsondef err(stream, msg, hdr):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not hdr.eof:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson stream.write("%s: line %d: %s\n" %
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson (hdr.filename, hdr.lineno, msg))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson stream.write("%s: %s\n" % (hdr.filename, msg))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Keyword strings (both expanded and literal) for the various SCMs
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson# Be certain to wrap each full expression in parens.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson#
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonidents = [
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # SCCS
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)',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson]
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsonIDENT = re.compile(r'(%s)' % '|'.join(idents))
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelsondef hdrchk(fh, filename=None, lenient=False, output=sys.stderr):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_ident = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guard = None
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 0
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson hdr = HeaderFile(fh, filename=filename, lenient=lenient)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 1:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
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 #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not hdr.has_copyright:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing copyright in opening comment", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
2f54b716e4d3cb0dc99066638fed631e3cbec97cRichard Lowe
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 2:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
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 found_ident = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 3: Header guards
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match = re.search(r'^#ifndef\s([a-zA-Z0-9_]+)$', line)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not match:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Invalid or missing header guard", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guard = match.group(1)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not lenient:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guardname = os.path.basename(hdr.filename)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # If we aren't being lenient, validate the name of the
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # guard
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guardname = guardname.upper()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guardname = guardname.replace('.', '_').replace('-','_')
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson guardname = guardname.replace('+', "_PLUS")
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not re.search(r'^_.*%s[_]?$' % guardname, guard):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Header guard does not match "
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson "suggested style (_FILEPATH_H_)", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not re.search(r'#define\s%s$' % guard, line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Invalid header guard", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not line:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Step 4: ident string
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # We allow both the keyword and extracted versions
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if (not found_ident and line.startswith("#pragma ident") and
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson not IDENT.search(line)):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Invalid #pragma ident", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments(line)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Main processing loop
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson in_cplusplus = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_endguard = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_cplusplus = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_code = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson while line:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not (line.startswith('#') or line.startswith('using')):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_code = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match = re.search(r'^#include(.*)$', line)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if match:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # For system files, make sure #includes are of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # '#include <file>'
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not lenient and not re.search(r'\s<.*>',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson match.group(1)):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Bad include", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif not in_cplusplus and re.search(r'^#ifdef\s__cplusplus$',
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Start of C++ header guard.
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Make sure it is of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # extern "C" {
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #endif
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if line == 'extern "C" {':
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if line != '#endif':
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Bad __cplusplus clause",
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson in_cplusplus = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_cplusplus = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif in_cplusplus and re.search(r'^#ifdef\s__cplusplus$', line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # End of C++ header guard. Make sure it is of the form:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #ifdef __cplusplus
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # }
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # #endif
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if line == '}':
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.getline()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if line != '#endif':
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Bad __cplusplus clause",
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson in_cplusplus = False
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson else:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson continue
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson elif re.search(r'^#endif\s/\* [!]?%s \*/$' % guard, line):
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Ending header guard
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson found_endguard = True
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson line = hdr.skipcomments()
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson # Check for missing end clauses
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson #
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if (not lenient) and (not found_cplusplus) and found_code:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing __cplusplus guard", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if in_cplusplus:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing closing #ifdef __cplusplus", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson if not found_endguard:
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson err(output, "Missing or invalid ending header guard", hdr)
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson ret = 1
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson
cdf0c1d55d9b3b6beaf994835440dfb01aef5cf0mjnelson return ret