1 #!/usr/perl5/bin/perl
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 #
24 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27
28 #
29 # Copyright (c) 2014 by Delphix. All rights reserved.
30 #
31
32 require 5.8.4;
33
34 $PNAME = $0;
35 $PNAME =~ s:.*/::;
36 $USAGE = "Usage: $PNAME [file ...]\n";
37 $errs = 0;
38
39 sub err
40 {
41 my($msg) = @_;
42
43 print "$file: $lineno: $msg\n";
44 $errs++;
45 }
46
47 sub dstyle
48 {
49 open(FILE, "$file");
50 $lineno = 0;
51 $inclause = 0;
52 $skipnext = 0;
53
54 while (<FILE>) {
55 $lineno++;
56
57 chop;
58
59 if ($skipnext) {
60 $skipnext = 0;
61 next;
62 }
63
64 #
65 # Amazingly, some ident strings are longer than 80 characters!
66 #
67 if (/^#pragma ident/) {
68 next;
69 }
70
71 #
72 # The algorithm to calculate line length from cstyle.
73 #
74 $line = $_;
75 if ($line =~ tr/\t/\t/ * 7 + length($line) > 80) {
76 # yes, there is a chance.
77 # replace tabs with spaces and check again.
78 $eline = $line;
79 1 while $eline =~
80 s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
81
82 if (length($eline) > 80) {
83 err "line > 80 characters";
84 }
85 }
86
87 if (/\/\*DSTYLED\*\//) {
88 $skipnext = 1;
89 next;
90 }
91
92 if (/^#pragma/) {
93 next;
94 }
95
96 if (/^#include/) {
97 next;
98 }
99
100 #
101 # Before we do any more analysis, we want to prune out any
102 # quoted strings. This is a bit tricky because we need
103 # to be careful of backslashed quotes within quoted strings.
104 # I'm sure there is a very crafty way to do this with a
105 # single regular expression, but that will have to wait for
106 # somone with better regex juju that I; we do this by first
107 # eliminating the backslashed quotes, and then eliminating
108 # whatever quoted strings are left. Note that we eliminate
109 # the string by replacing it with "quotedstr"; this is to
110 # allow lines to end with a quoted string. (If we simply
111 # eliminated the quoted string, dstyle might complain about
112 # the line ending in a space or tab.)
113 #
114 s/\\\"//g;
115 s/\"[^\"]*\"/quotedstr/g;
116
117 if (/[ \t]$/) {
118 err "space or tab at end of line";
119 }
120
121 if (/^[\t]+[ ]+[\t]+/) {
122 err "spaces between tabs";
123 }
124
125 if (/^[\t]* \*/) {
126 next;
127 }
128
129 if (/^ /) {
130 err "indented by spaces not tabs";
131 }
132
133 if (/^{}$/) {
134 next;
135 }
136
137 if (!/^enum/ && !/^\t*struct/ && !/^\t*union/ && !/^typedef/ &&
138 !/^translator/ && !/^provider/ && !/\tif / &&
139 !/ else /) {
140 if (/[\w\s]+{/) {
141 err "left brace not on its own line";
142 }
143
144 if (/{[\w\s]+/) {
145 err "left brace not on its own line";
146 }
147 }
148
149 if (!/;$/ && !/\t*}$/ && !/ else /) {
150 if (/[\w\s]+}/) {
151 err "right brace not on its own line";
152 }
153
154 if (/}[\w\s]+/) {
155 err "right brace not on its own line";
156 }
157 }
158
159 if (/^}/) {
160 $inclause = 0;
161 }
162
163 if (!$inclause && /^[\w ]+\//) {
164 err "predicate not at beginning of line";
165 }
166
167 if (!$inclause && /^\/[ \t]+\w/) {
168 err "space between '/' and expression in predicate";
169 }
170
171 if (!$inclause && /\w[ \t]+\/$/) {
172 err "space between expression and '/' in predicate";
173 }
174
175 if (!$inclause && /\s,/) {
176 err "space before comma in probe description";
177 }
178
179 if (!$inclause && /\w,[\w\s]/ && !/;$/) {
180 if (!/extern/ && !/\(/ && !/inline/) {
181 err "multiple probe descriptions on same line";
182 }
183 }
184
185 if ($inclause && /sizeof\(/) {
186 err "missing space after sizeof";
187 }
188
189 if ($inclause && /^[\w ]/) {
190 err "line doesn't begin with a tab";
191 }
192
193 if ($inclause && /,[\w]/) {
194 err "comma without trailing space";
195 }
196
197 if (/\w&&/ || /&&\w/ || /\w\|\|/ || /\|\|\w/) {
198 err "logical operator not set off with spaces";
199 }
200
201 #
202 # We want to catch "i<0" variants, but we don't want to
203 # erroneously flag translators.
204 #
205 if (!/\w<\w+>\(/) {
206 if (/\w>/ || / >\w/ || /\w</ || /<\w/) {
207 err "comparison operator not set " .
208 "off with spaces";
209 }
210 }
211
212 if (/\w==/ || /==\w/ || /\w<=/ || />=\w/ || /\w!=/ || /!=\w/) {
213 err "comparison operator not set off with spaces";
214 }
215
216 if (/\w=/ || /=\w/) {
217 err "assignment operator not set off with spaces";
218 }
219
220 if (/^{/) {
221 $inclause = 1;
222 }
223 }
224 }
225
226 foreach $arg (@ARGV) {
227 if (-f $arg) {
228 push(@files, $arg);
229 } else {
230 die "$PNAME: $arg is not a valid file\n";
231 }
232 }
233
234 die $USAGE if (scalar(@files) == 0);
235
236 foreach $file (@files) {
237 dstyle($file);
238 }
239
240 exit($errs != 0);