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);