1#! /usr/bin/env python2.7
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    # Ignore RISC-V assembly tests as they are maintained in an external
119    # project that does not follow the gem5 coding convention
120    _re_ignore("tests/test-progs/asmtest/src/riscv/"),
121    # Ignore RISC-V assembly dump files
122    _re_ignore("tests/test-progs/asmtest/dump/riscv/")
123]
124
125def check_ignores(fname):
126    """Check if a file name matches any of the ignore rules"""
127
128    for rule in style_ignores:
129        if rule(fname):
130            return True
131
132    return False
133
134
135def normalized_len(line):
136    """Return a normalized line length with expanded tabs"""
137
138    count = 0
139    for c in line:
140        if c == '\t':
141            count += tabsize - count % tabsize
142        else:
143            count += 1
144
145    return count
146
147def modified_regions(old, new, context=0):
148    regions = Regions()
149    m = difflib.SequenceMatcher(a=old, b=new, autojunk=False)
150    for group in m.get_grouped_opcodes(context):
151        first = group[0]
152        last = group[-1]
153
154        regions.extend(Region(first[3], last[4] + 1))
155
156    return regions
157