diff options
author | Damien Doligez <damien.doligez-inria.fr> | 2012-07-31 13:00:48 +0000 |
---|---|---|
committer | Damien Doligez <damien.doligez-inria.fr> | 2012-07-31 13:00:48 +0000 |
commit | 20e73da3a47dfc3cd719aff0c3cc72c301ea8359 (patch) | |
tree | 9fe9690a3a154b08cf7907c058064a88d7ea3de3 /tools/check-typo | |
parent | 997a678d5ee774930288bfec23d4b145ce45c078 (diff) | |
download | ocaml-20e73da3a47dfc3cd719aff0c3cc72c301ea8359.tar.gz |
Tool to check the OCaml sources for simple typographic rules (no TABs, etc)
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@12801 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'tools/check-typo')
-rwxr-xr-x | tools/check-typo | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/tools/check-typo b/tools/check-typo new file mode 100755 index 0000000000..427873b5d5 --- /dev/null +++ b/tools/check-typo @@ -0,0 +1,176 @@ +#!/bin/sh + +######################################################################### +# # +# OCaml # +# # +# Damien Doligez, projet Gallium, INRIA Rocquencourt # +# # +# Copyright 2012 Institut National de Recherche en Informatique et # +# en Automatique. All rights reserved. This file is distributed # +# under the terms of the Q Public License version 1.0. # +# # +######################################################################### + +# check-typo - Check typographic conventions on OCaml sources. + +# This program will check files for the following rules: + +# - absence of TAB characters (tab) +# - absence of non-ASCII characters (non-ascii) +# - absence of non-printing ASCII characters (non-printing) +# - absence of white space at end of line (white-at-eol) +# - absence of white lines at end of file (white-at-eof) +# - presence of a LF character at the end of the file (missing-lf) +# - maximum line length of 80 characters (long-line) + +# Exceptions are handled with a SVN property: "ocaml:typo". +# Its value for a given file is a comma-separated list of rule names, +# which lists the rules that should be disabled for this file. +# The rule names are the ones shown above in parentheses. + +# Built-in exceptions: +# - Any binary file (i.e. with svn:mime-type = application/octet-stream) +# is automatically exempt from all the rules. +# - Any file whose name begins with "Makefile" is automatically exempt +# from the "tabs" rule. + +# ASCII characters are bytes from 0 to 127. Any other byte is +# flagged as a non-ASCII character. + +# For the purpose of this tool, printing ASCII characters are: +# - the non-white printable ASCII characters (33 to 126) +# - TAB (09) +# - LF (10) +# - SPC (32) +# Anything else is flagged as a non-printing ASCII character. + +# This program will recursively explore the files and directories given +# on the command line (or by default the current directory), and check +# every file therein for compliance to the rules. + +# Directories named .svn and _build (and their contents) are always ignored. +# This program ignores any file that is not under svn control, unless +# explicitly given on the command line. + +# You can ignore a rule by giving the option -<rule> on the command +# line (before any file names). + +usage () { + echo "usage: check-typo {-<rule>} [--] [<file-or-dir> ...]" >&2 + exit 2 +} + +userrules='' + +while : ; do + case "$1" in + -*) userrules="${1#-},$userrules"; shift;; + --) shift; break;; + -*) usage;; + *) break;; + esac +done + +IGNORE_DIRS=' + -name .svn -prune -o + -name _build -prune -o +' + +( case $# in + 0) find . $IGNORE_DIRS -type f -print;; + *) for i in "$@"; do find "$i" $IGNORE_DIRS -type f -print; done;; + esac +) | ( + while read f; do + case `svn status "$f" 2>&1` in + '?'*) is_svn=false;; + I*) is_svn=false;; + svn:*"is not a working copy") is_svn=false;; + *) is_svn=true;; + esac + case "$*" in + *$f*) is_cmd_line=true;; + *) is_cmd_line=false;; + esac + if $is_svn || $is_cmd_line; then :; else continue; fi + svnrules='' + if $is_svn; then + case `svn propget svn:mime-type "$f"` in + application/octet-stream) continue;; + esac + svnrules=`svn propget ocaml:typo "$f"` + fi + rules="$userrules" + case "$f" in + Makefile*) rules="tab,$rules";; + */Makefile*) rules="tab,$rules";; + esac + + (cat "$f"; echo) \ + | awk -v rules="$rules" -v svnrules="$svnrules" -v file="$f" \ + ' + function err(name, msg) { + ++ counts[name]; + if (!index(("," rules svnrules ","), ("," name ",")) \ + && counts[name] <= 10){ + printf ("%s:%d.%d:", file, NR, RSTART + RLENGTH); + printf (" [%s] %s\n", name, msg); + if (counts[name] == 10){ + printf ("WARNING: too many [%s] in this file.", name); + printf (" Others will not be reported.\n"); + } + } + } + + match($0, /\t/) { + err("tab", "TAB character(s)"); + } + + match($0, /[\200-\377]/) { + err("non-ascii", "non-ASCII character(s)"); + } + + match($0, /[^\t\200-\377 -~]/) { + err("non-printing", "non-printing ASCII character(s)"); + } + + match($0, /[ \t]+$/) { + err("white-at-eol", "whitespace at end of line"); + } + + length($0) > 80 { + RSTART = 81; + RLENGTH = length($0) - 81; + err("long-line", "line is over 80 characters"); + } + + { + prev_line = last_line; + last_line = $0; + } + + END { + if (match(last_line, /.+/)){ + err("missing-lf", "missing linefeed at EOF"); + prev_line = last_line; + ++ NR; + empty_file = 0; + }else{ + empty_file = NR == 1; + } + if (!empty_file && match(prev_line, /^[ \t]*$/)){ + err("white-at-eof", "white line(s) at EOF"); + } + split(svnrules, r, ","); + for (i in r){ + name = r[i]; + if (name != "" && !counts[name]){ + printf ("%s, line 1, char 1: unused rule exception [%s]\n", + file, name); + } + } + } + ' + done +) |