Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

352 lines
9.2 KiB

  1. @rem = '
  2. @perl.exe %~f0 %*
  3. @goto :EOF
  4. '; undef @rem;
  5. #
  6. # This script verifies adherence to the style document
  7. #
  8. # Include 'spelling.pl' from the same directory as this script
  9. $dir=$0; $dir =~ s/\\[^\\]*$//;
  10. require "$dir\\spelling.pl";
  11. # List of error classes to keep quiet about
  12. # Options: (spell_c, indent, line_length, tabs, braces, eof)
  13. @suppress_errors = (spell_c);
  14. foreach $t (@suppress_errors) { $suppress_errors{$t} = 1; }
  15. # Process command-line options
  16. @args=@ARGV;
  17. undef @ARGV;
  18. $syntax = "style [-?] [<file> ...]";
  19. for ($i=0;$i<=$#args;$i++) {
  20. $_ = $args[$i];
  21. if (0) {
  22. } elsif (/^[-\/]\w$/) {
  23. $writeSpellingErrors = 1;
  24. } elsif (/^[-\/]\?$/) {
  25. print <<EOT;
  26. $syntax
  27. Checks adherence to the style document.
  28. -w Writes misspelt words in comments to spelling.err
  29. EOT
  30. exit 0;
  31. } else {
  32. push (@ARGV,$_);
  33. }
  34. }
  35. if ($#ARGV>=0) {
  36. @filespecs = @ARGV;
  37. }
  38. # Supply a default file set if none given
  39. @exts = ("cpp", "cxx", "c", "h", "hxx", "hpp");
  40. if ($#filespecs<0) { @filespecs = map("*.$_", @exts); }
  41. # Subroutines
  42. # Report a file-wide error
  43. sub fileError {
  44. local ($type, $string) = @_;
  45. return if $suppress_errors{$type};
  46. print "$filename: $string\n";
  47. }
  48. # Report an error at a given line
  49. sub lineError {
  50. local ($type, $string) = @_;
  51. return if $suppress_errors{$type};
  52. print "$filename($line): $string\n";
  53. }
  54. # Spellcheck a comment
  55. sub checkComment {
  56. local ($_) = @_;
  57. while (/([a-zA-Z_0-9']*)/g) {
  58. my $word=$1;
  59. # Skip numbers
  60. next if ($word =~ /^[0-9]*[Ll]?$/);
  61. next if ($word =~ /^0[Xx][0-9a-fA-F]+[lL]?$/);
  62. # Skip words 3 or fewer letters long, containing digits
  63. next if ($word =~ /[0-9]/ && length($word)<=3);
  64. # Remove leading/trailing hyphens
  65. $word =~ s/^'//g;
  66. $word =~ s/'$//g;
  67. next if !$word;
  68. # Try an exact match against the English dictionary
  69. next if $dic_english{$word};
  70. # Try the code dictionary
  71. next if $dic_code{$word};
  72. # Check for shifty words
  73. if ($dic_shifty{$word}) {
  74. &lineError("spell_c", "Shifty word: \"$word\"");
  75. next;
  76. }
  77. # If it's capitalized, or all caps, look for the lowercase
  78. # version in the English dictionary
  79. if ($word =~ /^([A-Z])([^A-Z]*)$/) {
  80. my $i = $1;
  81. $i =~ tr/A-Z/a-z/;
  82. next if $dic_english{"$i$2"};
  83. } elsif ($word !~ /[a-z]/) {
  84. $word =~ tr/A-Z/a-z/;
  85. next if $dic_english{"$i$2"};
  86. }
  87. # Okay, it's a spelling error
  88. if ($writeSpellingErrors) {
  89. # Put it in the English error list if it's not recognizably an
  90. # identifier
  91. if (($word !~ /^.+[A-Z0-9]/) && ($word !~ /_/)) {
  92. push (@errors_english, $word);
  93. } else {
  94. push (@errors_code, $word);
  95. }
  96. } else {
  97. &lineError("spell_c", "Misspelt word: \"$word\"");
  98. }
  99. }
  100. }
  101. &loadDictionaries() unless $suppress_errors{spell_c};
  102. # Check the indentation level
  103. #
  104. # Uses $lastIndentErrorLine and $actualIndent
  105. sub checkIndent {
  106. my $pos;
  107. foreach $pos (@_) {
  108. if ($pos == $actualIndent) {
  109. return 1;
  110. }
  111. }
  112. if ($line != $lastIndentErrorLine) {
  113. &lineError("indent", "Indentation error: Actual pos $actualIndent, expected ".
  114. join(', ', grep($_ != -1, @_)));
  115. $lastIndentErrorLine = $line;
  116. }
  117. return 0;
  118. }
  119. sub currentIndent {
  120. $mainIndentPos[$#mainIndentPos];
  121. }
  122. # Evil function which references these global variables:
  123. # FILE, $line, $altindentpos, $lineAccum, $commentAccum, $tempindentpos
  124. sub getLine {
  125. local $_;
  126. LINE:
  127. {
  128. $_ = <FILE>;
  129. defined($_) || last;
  130. chop;
  131. $line++;
  132. # Check line length
  133. /^(.*)$/;
  134. my $l = length($1);
  135. if ($l > 80) {
  136. &lineError("line_length", "Line too long");
  137. }
  138. # Accumulate lines which have escaped newlines
  139. if (/\\$/) {
  140. $lineAccum .= $_;
  141. redo LINE;
  142. } elsif (defined ($lineAccum)) {
  143. $lineAccum .= $_;
  144. $_ = $lineAccum;
  145. $lineAccum = undef;
  146. }
  147. COMMENTLOOP:
  148. {
  149. # Accumulate comments
  150. if (defined($commentAccum)) {
  151. if (s;^(.*?)\*/;;) {
  152. # End of multi-line comment
  153. $commentAccum .= " $1";
  154. &checkComment($commentAccum);
  155. $commentAccum = undef;
  156. } else {
  157. # Inside multi-line comment
  158. $commentAccum .= " $_";
  159. redo LINE;
  160. }
  161. }
  162. if ((s;//(.*)$;;) || (s;/\*(.*?)\*/;;)) {
  163. # Single-line comment - either // or /* ... */
  164. &checkComment($1);
  165. redo COMMENTLOOP;
  166. }
  167. if (s;/\*(.*)$;;) {
  168. # Start of multi-line comment
  169. $commentAccum = $1;
  170. }
  171. }
  172. # Skip blank lines
  173. redo LINE if /^\s*$/;
  174. # No tabs allowed
  175. if (s/\t/ /g) {
  176. &lineError("tabs", "Line contains tab characters");
  177. }
  178. #
  179. # Indentation checking
  180. #
  181. /^( *)[^ ]/;
  182. local $actualIndent = length($1);
  183. # Was the previous line #if* ?
  184. if ($prevLineHashIf) {
  185. $prevLineHashIf = 0;
  186. &checkIndent(&currentIndent, &currentIndent+4);
  187. push(@mainIndentPos, $actualIndent);
  188. }
  189. # #if*, #endif
  190. if (/^ *#if/ || /^ *#endif/) {
  191. if (/^ *#if/) {
  192. $prevLineHashIf = 1;
  193. } else {
  194. pop(@mainIndentPos);
  195. }
  196. &checkIndent(&currentIndent);
  197. redo LINE;
  198. }
  199. # #else
  200. if (/^ *#else/) {
  201. &checkIndent($mainIndentPos[$#mainIndentPos-1]);
  202. redo LINE;
  203. }
  204. # Process braces.
  205. my $braceDelta = 0;
  206. while (/{/g) { $braceDelta++; }
  207. while (/}/g) { $braceDelta--; }
  208. if ($braceDelta != 0) {
  209. # Check for braces not on their own lines (except for matched braces)
  210. if (!/^[\s{};]*$/) {
  211. &lineError("braces", "Brace should be on separate line");
  212. }
  213. if ($braceDelta > 0) {
  214. &checkIndent(&currentIndent);
  215. push(@mainIndentPos, $actualIndent+4);
  216. } else {
  217. pop(@mainIndentPos);
  218. &checkIndent(&currentIndent);
  219. }
  220. redo LINE;
  221. }
  222. # Certain constructs effectively cause a temporary unindent by one
  223. # level. These are:
  224. # "case XYZ:","default:", "public:", "private:",
  225. # "protected:", and labels.
  226. if (/case .*:/ || /default:/ || /public:/ || /private:/ ||
  227. /protected:/ || /^ *[a-zA-Z_0-9]+: *$/) {
  228. &checkIndent(&currentIndent-4);
  229. redo LINE;
  230. }
  231. # Test the indent level
  232. # Hack - for now, $tempindentpos!=-1, we skip the check
  233. if ($tempIndentPos == -1) {
  234. &checkIndent(&currentIndent, $altIndentPos, $tempIndentPos);
  235. }
  236. # Multi-line statements may be temporarily indented
  237. if (($braceDelta == 0) && (!/; *$/)) {
  238. $tempIndentPos = &currentIndent+4;
  239. } else {
  240. $tempIndentPos = -1;
  241. }
  242. }
  243. $_;
  244. }
  245. # Evil function which references global variables $token, $ttype, FILE
  246. sub getToken {
  247. while (1) {
  248. if ($parseLine =~ /^\s*$/) {
  249. $parseLine = &getLine();
  250. $parseLine || return 0;
  251. next;
  252. }
  253. # if (/([0-9\.]([0-9e\.]*))\b/g) {
  254. # }
  255. # $token = $1;
  256. # for now, eat everything
  257. $parseLine = "";
  258. }
  259. return 1;
  260. }
  261. $findstr = "dir /b " . join(" ", @filespecs)." 2>nul";
  262. open(FIND, "$findstr|");
  263. @files = <FIND>;
  264. close(FIND);
  265. # Remove blank lines
  266. @files = grep(!/^\s*$/, @files);
  267. chop @files;
  268. $#files >= 0 || die "No files found (".join(", ", @filespecs).").\n";
  269. foreach $filename (@files) {
  270. open(FILE, "$filename");
  271. # Remove path from filename
  272. $filename =~ s/.*\\([^\\]*)/$1/;
  273. $line=0;
  274. $lastIndentErrorLine=0;
  275. $tempIndentPos = -1; # Temporary indentation, used for multi-line statements
  276. @mainIndentPos = (0); # Stack of indent positions
  277. $prevLineHashIf = 0; # If true, the previous line was a #if
  278. $parseLine = "";
  279. undef $lineAccum;
  280. undef $commentAccum;
  281. while (&getToken()) {
  282. }
  283. close(FILE);
  284. if (defined($lineAccum) || defined($commentAccum)) {
  285. &lineError("eof", "Unexpected EOF");
  286. }
  287. }
  288. if ($writeSpellingErrors) {
  289. &writeSpellingErrors("english", "code");
  290. }