svn commit: r241598 - user/crees/rclint
Chris Rees
crees at FreeBSD.org
Mon Oct 15 20:19:58 UTC 2012
Author: crees (ports committer)
Date: Mon Oct 15 20:19:57 2012
New Revision: 241598
URL: http://svn.freebsd.org/changeset/base/241598
Log:
Split into functions; code is only used once, but separating makes it easier
to read
Check default variable assignments and be very fussy
Use \ instead of : as error delimiter
Modified:
user/crees/rclint/errors.en
user/crees/rclint/rclint.py
Modified: user/crees/rclint/errors.en
==============================================================================
--- user/crees/rclint/errors.en Mon Oct 15 18:15:18 2012 (r241597)
+++ user/crees/rclint/errors.en Mon Oct 15 20:19:57 2012 (r241598)
@@ -1,15 +1,31 @@
-# Rigid format of this file; colon-separated tuples to define
+# Rigid format of this file; backslash-separated tuples to define
# error messages and explanations.
# format as follows:
-error_id:message:explanation
-name_missing:name is set late or not at all:Directly following the sourcing of scripts must follow setting of the variable name.
-name_quoted:name is quoted:Do not quote the value of name. If it has spaces, use underscores.
-rc_subr_late:rc.subr sourcing late or nonexistent:The first non-comment non-blank line in any rc file must be sourcing /etc/rc.subr.
-rcorder_keyword_freebsd:Do not include FreeBSD in the KEYWORD rcorder line:Historically FreeBSD scripts were marked in the KEYWORD section. This is no longer necessary.
-rcorder_missing:Missing rcorder block:Following the FreeBSD RCSId keyword must be nothing but empty comment lines and an rcorder block.
-rcorder_order:rcorder block in the wrong order; should be PROVIDE/REQUIRE/BEFORE/KEYWORD:See the article on RC scripting.
-rcvar_incorrect:rcvar is not set correctly:rcvar must be directly set to name_enable. Do not quote, and do not use indirection; ${name}_enable is slower than example_enable.
-rcvar_missing:rcvar is set late or not at all:Setting rcvar must be done straight after setting name.
-rcvar_quoted:rcvar is quoted:Do not quote the value of rcvar.
-rcsid:Missing FreeBSD RCSId keyword:All rc scripts must contain a line beginning # $FreeBSD$. Do not include blank lines without comment markers at the beginning (#) until the script begins.
-shebang:Incorrect shebang used:All rc scripts must start with the correct shebang; #!/bin/sh.
+error_id\message\explanation
+
+defaults_invalid\Invalid lines in defaults block.\Allowed are variable assignments (including eval statements) and comments. A blank line ends the block.
+defaults_mandatory_colon\Override blanks in mandatory values (:=/:- vs =/-)\Values that must not be blank (such as _enable) should be set by default as ${var:=value}; thus disallowing blank values (man sh)
+defaults_non_mandatory_colon\Do not clobber blank values for non-mandatory variables\Syntax for variables that are not mandatory is ${var=value}; including := will override var="" set in rc.conf (man sh)
+defaults_old_style\Prefer condensed version for setting default values of variables\When setting the default value for a variable, it is much less verbose and clearer to use the : ${variable=var} notation, as well as it being obvious that the source and destination variable are the same
+defaults_value_quoted\Do not quote values set by default\With the syntax ${variable=value}, value can even contain spaces and does not need quoting
+
+load_rc_config_extra\load_rc_config not followed by blank line\The load_rc_config line must form its own block
+load_rc_config_missing\load_rc_config is late, incorrect or missing\Directly following the name/rcvar block must be load_rc_config $name, unquoted
+
+name_missing\name is set late or not at all\Directly following the sourcing of scripts must follow setting of the variable name
+name_quoted\name is quoted\Do not quote the value of name. If it has spaces, use underscores
+
+rc_subr_late\rc.subr sourcing late or nonexistent\The first non-comment non-blank line in any rc file must be sourcing /etc/rc.subr
+
+rcorder_keyword_freebsd\Do not include FreeBSD in the KEYWORD rcorder line\Historically FreeBSD scripts were marked in the KEYWORD section. This is no longer necessary
+rcorder_missing\Missing rcorder block\Following the FreeBSD RCSId keyword must be nothing but empty comment lines and an rcorder block
+rcorder_order\rcorder block in the wrong order; should be PROVIDE/REQUIRE/BEFORE/KEYWORD\See the article on RC scripting
+
+rcvar_extra\extra lines in name/rcvar block\Order should be [blank line]/name=/rcvar=/[blank line]
+rcvar_incorrect\rcvar is not set correctly\rcvar must be directly set to name_enable. Do not quote, and do not use indirection; ${name}_enable is slower than example_enable
+rcvar_missing\rcvar is set late or not at all\Setting rcvar must be done straight after setting name
+rcvar_quoted\rcvar is quoted\Do not quote the value of rcvar
+
+rcsid\Missing FreeBSD RCSId keyword\All rc scripts must contain a line beginning # $FreeBSD$. Do not include blank lines without comment markers at the beginning (#) until the script begins
+
+shebang\Incorrect shebang used\All rc scripts must start with the correct shebang; #!/bin/sh
Modified: user/crees/rclint/rclint.py
==============================================================================
--- user/crees/rclint/rclint.py Mon Oct 15 18:15:18 2012 (r241597)
+++ user/crees/rclint/rclint.py Mon Oct 15 20:19:57 2012 (r241598)
@@ -32,9 +32,10 @@ micro = 0
import argparse
import logging
import re
+import textwrap
def error_explain(error):
- if verbosity > 0: print error['explanation']
+ if verbosity > 0: print textwrap.fill(error['explanation'], initial_indent='==> ', subsequent_indent=' ')
def error(type, line_number, filename):
logging.error("[%d]%s: %s " % (line_number, filename, errors[type]['message']))
@@ -43,6 +44,10 @@ def error(type, line_number, filename):
def check_quoted(string):
return True if string[0] == '"' or string[0] == "'" else False
+def mandatory(var):
+ mand = ['enable']
+ return True if var.split('_')[-1] in mand else False
+
def get_value(var, line):
n = re.match('%s=(\S*)$' % var, line)
if n:
@@ -51,11 +56,7 @@ def get_value(var, line):
else:
return False
-def do_rclint(filename):
- logging.debug('Suck in file %s' % filename)
- lines=[line.rstrip('\n') for line in open(filename)]
- num = 0
-
+def check_header(lines, num, filename):
# Basic order; shebang, copyright, RCSId, gap, rcorder
logging.debug('Check shebang')
@@ -97,8 +98,9 @@ def do_rclint(filename):
if re.match('# [PRBK]', lines[num]):
error('rcorder_order', num, filename)
- documentation_line = num
+ return num
+def check_intro(lines, num, filename):
logging.debug('Checking sourcing lines')
while lines[num] == '' or lines[num][0] == '#':
num += 1
@@ -130,7 +132,67 @@ def do_rclint(filename):
error('rcvar_incorrect', num, filename)
else:
num += 1
-
+
+ logging.debug('Checking load_rc_config')
+ if lines[num] == '':
+ num += 1
+ else:
+ error('rcvar_extra', num, filename)
+
+ if re.match('load_rc_config (?:\$name|%s)' % name, lines[num]):
+ num += 1
+ else:
+ error('load_rc_config_missing', num, filename)
+
+ if lines[num] == '':
+ num += 1
+ else:
+ error('load_rc_config_extra', num, filename)
+
+ return num
+
+def check_defaults(lines, num, filename):
+ logging.debug('Checking defaults set')
+
+ default = { }
+ try:
+ while lines[num] != '':
+ while lines[num][0] == '#' or lines[num][:4] == 'eval': num += 1
+ if lines[num][0] == ':':
+ # Shorthand set self-default assignment
+ (target, operator, value) = re.match(': \${([^:=]+)(:?=)([^}]+)}', lines[num]).groups()
+ if operator == ':=' and not mandatory(target):
+ error('defaults_non_mandatory_colon', num, filename)
+ elif operator == '=' and mandatory(target):
+ error('defaults_mandatory_colon', num, filename)
+
+ else:
+ # Longhand set default assignment
+ (target, source, operator, value) = re.match('([^=]+)=\${([^:-]+)(:?-)([^}]+)}', lines[num]).groups()
+ if target == source:
+ error('defaults_old_style', num, filename)
+
+ if operator == ':-' and not mandatory(target):
+ error('defaults_non_mandatory_colon', num, filename)
+ elif operator == '-' and mandatory(target):
+ error('defaults_mandatory_colon', num, filename)
+
+ if check_quoted(value):
+ error('defaults_value_quoted', num, filename)
+
+ num += 1
+ except:
+ error('defaults_invalid', num, filename)
+
+def do_rclint(filename):
+ logging.debug('Suck in file %s' % filename)
+ lines=[line.rstrip('\n') for line in open(filename)]
+ begin_num = 0
+
+ endofheader_num = check_header(lines, begin_num, filename)
+ endofintro_num = check_intro(lines, endofheader_num, filename)
+ endofdefaults_num = check_defaults(lines, endofintro_num, filename)
+
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs = '+')
@@ -151,7 +213,7 @@ try:
for e in f.readlines():
if e[0] == '#' or len(e) == 1:
continue
- e = e.split(':')
+ e = e.split('\\')
errors[e[0]] = { 'message': e[1], 'explanation': e[2] }
except:
logging.error('Cannot open database for language %s' % errordb)
More information about the svn-src-user
mailing list