1#!/usr/local/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, 2016 by Delphix. All rights reserved. 30# 31 32require 5.8.4; 33 34$PNAME = $0; 35$PNAME =~ s:.*/::; 36$USAGE = "Usage: $PNAME [file ...]\n"; 37$errs = 0; 38 39sub err 40{ 41 my($msg) = @_; 42 43 print "$file: $lineno: $msg\n"; 44 $errs++; 45} 46 47sub 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 226foreach $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 234die $USAGE if (scalar(@files) == 0); 235 236foreach $file (@files) { 237 dstyle($file); 238} 239 240exit($errs != 0); 241