style.py revision 11828:36b064696175
1#! /usr/bin/env python2
2# Copyright (c) 2014, 2016 ARM Limited
3# All rights reserved
4#
5# The license below extends only to copyright in the software and shall
6# not be construed as granting a license to any other intellectual
7# property including but not limited to intellectual property relating
8# to a hardware implementation of the functionality of the software
9# licensed hereunder.  You may use the software subject to the license
10# terms below provided that you ensure that this notice is replicated
11# unmodified and in its entirety in all distributions of the software,
12# modified or unmodified, in source code or in binary form.
13#
14# Copyright (c) 2006 The Regents of The University of Michigan
15# Copyright (c) 2007,2011 The Hewlett-Packard Development Company
16# Copyright (c) 2016 Advanced Micro Devices, Inc.
17# All rights reserved.
18#
19# Redistribution and use in source and binary forms, with or without
20# modification, are permitted provided that the following conditions are
21# met: redistributions of source code must retain the above copyright
22# notice, this list of conditions and the following disclaimer;
23# redistributions in binary form must reproduce the above copyright
24# notice, this list of conditions and the following disclaimer in the
25# documentation and/or other materials provided with the distribution;
26# neither the name of the copyright holders nor the names of its
27# contributors may be used to endorse or promote products derived from
28# this software without specific prior written permission.
29#
30# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41#
42# Authors: Nathan Binkert
43#          Steve Reinhardt
44#          Andreas Sandberg
45
46from abc import ABCMeta, abstractmethod
47import difflib
48import re
49import sys
50
51from region import *
52
53tabsize = 8
54lead = re.compile(r'^([ \t]+)')
55trail = re.compile(r'([ \t]+)$')
56any_control = re.compile(r'\b(if|while|for)([ \t]*)\(')
57
58
59class UserInterface(object):
60    __metaclass__ = ABCMeta
61
62    def __init__(self, verbose=False):
63        self.verbose = verbose
64
65    def prompt(self, prompt, results, default):
66        while True:
67            result = self._prompt(prompt, results, default)
68            if result in results:
69                return result
70
71    @abstractmethod
72    def _prompt(self, prompt, results, default):
73        pass
74
75    @abstractmethod
76    def write(self, string):
77        pass
78
79class StdioUI(UserInterface):
80    def _prompt(self, prompt, results, default):
81        return raw_input(prompt) or default
82
83    def write(self, string):
84        sys.stdout.write(string)
85
86class MercurialUI(UserInterface):
87    def __init__(self, ui, *args, **kwargs):
88        super(MercurialUI, self).__init__(*args, **kwargs)
89        self.hg_ui = ui
90
91    def _prompt(self, prompt, results, default):
92        return self.hg_ui.prompt(prompt, default=default)
93
94    def write(self, string):
95        self.hg_ui.write(string)
96
97
98def _re_ignore(expr):
99    """Helper function to create regular expression ignore file
100    matcher functions"""
101
102    rex = re.compile(expr)
103    def match_re(fname):
104        return rex.match(fname)
105    return match_re
106
107# This list contains a list of functions that are called to determine
108# if a file should be excluded from the style matching rules or
109# not. The functions are called with the file name relative to the
110# repository root (without a leading slash) as their argument. A file
111# is excluded if any function in the list returns true.
112style_ignores = [
113    # Ignore external projects as they are unlikely to follow the gem5
114    # coding convention.
115    _re_ignore("^ext/"),
116    # Ignore test data, as they are not code
117    _re_ignore("^tests/(?:quick|long)/"),
118]
119
120def check_ignores(fname):
121    """Check if a file name matches any of the ignore rules"""
122
123    for rule in style_ignores:
124        if rule(fname):
125            return True
126
127    return False
128
129
130def normalized_len(line):
131    """Return a normalized line length with expanded tabs"""
132
133    count = 0
134    for c in line:
135        if c == '\t':
136            count += tabsize - count % tabsize
137        else:
138            count += 1
139
140    return count
141
142def modified_regions(old, new, context=0):
143    regions = Regions()
144    m = difflib.SequenceMatcher(a=old, b=new, autojunk=False)
145    for group in m.get_grouped_opcodes(context):
146        first = group[0]
147        last = group[-1]
148
149        regions.extend(Region(first[3], last[4] + 1))
150
151    return regions
152