--- /dev/null
+#! /usr/bin/env ruby
+
+# This script loosely checks:
+# - Macros used before they are defined
+# - Non-command functions which may never be used
+
+# To run,
+# $ for i in liece-[a-z]*.el; ../etc/check-subrs.rb $i *.el~$i
+
+def scan_inlines(data)
+ result = []
+ data.scan(/^\((?:defmacro|defsubst)\s+(\S+)/) {|name,|
+ pos = Regexp.last_match.begin(1)
+ result << [pos, name]
+ }
+ result
+end
+
+def scan_subrs(data)
+ result = []
+ data.scan(/^\(defun\s+(\S+)\s*\([^\)]*\)\s*\
+((?:"[^"]*")?\s*\(interactive\b)?/) {|name, i|
+ pos = Regexp.last_match.begin(1)
+ result << [pos, name] unless i
+ }
+ result
+end
+
+def count_call(name, data)
+ count = 0
+ data.scan(/\b#{name}\b/) {
+ count += 1
+ }
+ count
+end
+
+symbols = []
+File.open(ARGV[0]) {|file|
+ data = file.read
+ symbols = scan_inlines(data)
+ symbols.each {|pos, name|
+ if /\b#{name}\b/ && Regexp.last_match.begin(0) < pos
+ puts("#{name} is called before its definition")
+ end
+ }
+ symbols |= scan_subrs(data)
+}
+
+symbols.each {|pos, name|
+ count = 0
+ ARGV.each {|source|
+ File.open(source) {|file|
+ data = file.read
+ count += count_call(name, data)
+ }
+ }
+ if count < 2
+ puts("#{name} may not be called")
+ end
+}