OpenPKG CVS Repository
http://cvs.openpkg.org/
____________________________________________________________________________
Server: cvs.openpkg.org Name: Thomas Lotterer
Root: /e/openpkg/cvs Email: [EMAIL PROTECTED]
Module: openpkg-re Date: 08-Jul-2003 00:11:25
Branch: HEAD Handle: 2003070723112400
Added files:
openpkg-re rclint.pl
Log:
first cut for a rc. file lint; code taken from speclint/rpmlint
Summary:
Revision Changes Path
1.1 +287 -0 openpkg-re/rclint.pl
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: openpkg-re/rclint.pl
============================================================================
$ cvs diff -u -r0 -r1.1 rclint.pl
--- /dev/null 2003-07-08 00:11:25.000000000 +0200
+++ rclint.pl 2003-07-08 00:11:25.000000000 +0200
@@ -0,0 +1,287 @@
+#!/bin/sh -- # -*- perl -*-
+eval 'exec perl -S $0 ${1+"$@"}'
+ if $running_under_some_shell;
+##
+## rclint -- OpenPKG rc. File Checker
+## Copyright (c) 2003 The OpenPKG Project <http://www.openpkg.org/>
+## Copyright (c) 2003 Ralf S. Engelschall <[EMAIL PROTECTED]>
+## Copyright (c) 2003 Cable & Wireless <http://www.cw.com/>
+##
+## Permission to use, copy, modify, and distribute this software for
+## any purpose with or without fee is hereby granted, provided that
+## the above copyright notice and this permission notice appear in all
+## copies.
+##
+## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
+## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+## SUCH DAMAGE.
+##
+
+require 5;
+use Getopt::Long;
+use IO;
+use strict;
+
+# program information
+my $progname = "rclint";
+my $progvers = "0.0.1";
+
+# parameters (defaults)
+my $version = 0;
+my $verbose = 0;
+my $help = 0;
+my $check = 'all';
+my $tmpdir = ($ENV{TMPDIR} || $ENV{TEMPDIR} || "/tmp") . "/$progname";
+my $rpm = 'rpm';
+my $rpm2cpio = 'rpm2cpio';
+
+# exception handling support
+$SIG{__DIE__} = sub {
+ my ($err) = @_;
+ $err =~ s|\s+at\s+.*||s if (not $verbose);
+ print STDERR "$progname:ERROR: $err ". ($! ? "($!)" : "") . "\n";
+ exit(1);
+};
+
+# command line parsing
+Getopt::Long::Configure("bundling");
+my $result = GetOptions(
+ 'V|version' => \$version,
+ 'v|verbose' => \$verbose,
+ 'h|help' => \$help,
+ 'c|check=s' => \$check,
+ 't|tmpdir=s' => \$tmpdir,
+ 'r|rpm=s' => \$rpm,
+) || die "option parsing failed";
+if ($help) {
+ print "Usage: $progname [options] [RPMFILE ...]\n" .
+ "Available options:\n" .
+ " -v,--verbose enable verbose run-time mode\n" .
+ " -h,--help print out this usage page\n" .
+ " -c,--check=CHECKS select checks to perform (default='all')\n" .
+ " -r,--rpm=FILE filesystem path to RPM program\n" .
+ " -t,--tmpdir=PATH filesystem path to temporary directory\n" .
+ " -V,--version print program version\n" .
+ exit(0);
+}
+if ($version) {
+ print "OpenPKG $progname $progvers\n";
+ exit(0);
+}
+
+# verbose message printing
+sub msg_verbose {
+ my ($msg) = @_;
+ print STDERR "$msg\n" if ($verbose);
+}
+
+# warning message printing
+sub msg_warning {
+ my ($msg) = @_;
+ print STDERR "$progname:WARNING: $msg\n";
+}
+
+# error message printing
+sub msg_error {
+ my ($msg) = @_;
+ print STDERR "$progname:ERROR: $msg\n";
+}
+
+# determine check list
+my @check_list = (qw(
+ blank
+ comment
+));
+my @checks = ();
+if ($check eq 'all') {
+ @checks = @check_list;
+}
+else {
+ foreach my $c (split(/,/, $check)) {
+ if (not grep(/^$c$/, @check_list)) {
+ die "invalid check \"$c\"";
+ }
+ push(@checks, $c);
+ }
+}
+
+# global return code
+$main::GRC = 0;
+
+# environment preparation
+system("rm -rf $tmpdir");
+system("mkdir -p $tmpdir");
+
+# iterate over all rc. files
+foreach my $filename (@ARGV) {
+ my $io = new IO::File "<$filename"
+ or die "unable to open file \"$filename\" for reading";
+ my $spec; { local $/ = undef; $spec = <$io>; }
+ $io->close;
+ foreach my $check (@checks) {
+ eval "\&check_$check(\$filename, \$spec);";
+ }
+}
+
+# environment cleanup
+system("rm -rf $tmpdir");
+
+# die gracefully
+exit($main::GRC);
+
+## _________________________________________________________________
+##
+## COMMON SUBROUTINES
+## _________________________________________________________________
+##
+
+sub lines {
+ my ($txt) = @_;
+ my $l = 0;
+ $txt =~ s|\n|$l++, ''|sge;
+ return $l;
+}
+
+sub lint_message {
+ my ($type, $file, $done, $this, $msg) = @_;
+ if (defined($done) and defined($this)) {
+ my $start = &lines($done) + 1;
+ my $end = $start + &lines($this);
+ my $pos = $start;
+ $pos .= "-". $end if ($end > $start);
+ printf("%s:%s: %s:%s: %s\n", $progname, $type, $file, $pos, $msg);
+ }
+ else {
+ printf("%s:%s: %s: %s\n", $progname, $type, $file, $msg);
+ }
+}
+
+sub lint_warning {
+ my ($file, $done, $this, $msg) = @_;
+ &lint_message("WARNING", $file, $done, $this, $msg);
+ $main::GRC = 1 if ($main::GRC < 1);
+}
+
+sub lint_error {
+ my ($file, $done, $this, $msg) = @_;
+ &lint_message("ERROR", $file, $done, $this, $msg);
+ $main::GRC = 2 if ($main::GRC < 2);
+}
+
+## _________________________________________________________________
+##
+## CHECK "blank": whitespace and blank lines
+## _________________________________________________________________
+##
+
+sub check_blank {
+ my ($file, $spec) = @_;
+
+ # check for CR-LF combination
+ my $done = ''; my $this = ''; my $todo = $spec;
+ while ($todo =~ m/\r\n/s) {
+ $done .= $`; $this = $&; $todo = $';
+ &lint_warning($file, $done, $this, "carriage-return (CR, 0x0d) line-feed
(NL, 0x0a) combination (expected just line-feed)");
+ $done .= $this;
+ }
+
+ # check for multiple blank lines
+ $done = ''; $this = ''; $todo = $spec;
+ while ($todo =~ m/(\r?\n[ \t]*){3,}/s) {
+ $done .= $`; $this = $&; $todo = $';
+ &lint_warning($file, $done, $this, "multiple subsequent blank lines
(expected single blank line)");
+ $done .= $this;
+ }
+
+ # check for trailing whitespaces
+ $done = ''; $this = ''; $todo = $spec;
+ while ($todo =~ m/[ \t]+\r?\n/s) {
+ $done .= $`; $this = $&; $todo = $';
+ if ($done eq '' or $done =~ m|\n$|s) {
+ &lint_warning($file, $done, $this, "whitespace on empty line (expected
none)");
+ }
+ else {
+ &lint_warning($file, $done, $this, "trailing whitespace (expected
none)");
+ }
+ $done .= $this;
+ }
+
+ # check for bogus line continuations
+ $done = ''; $this = ''; $todo = $spec;
+ while ($todo =~ m/\\[ \t]*\r?\n(?=[ \t]*\r?\n)/s) {
+ $done .= $`; $this = $&; $todo = $';
+ &lint_warning($file, $done, $this, "bogus line continuation for following
empty line (expect no line continuation)");
+ $done .= $this;
+ }
+
+ # check for leading whitespaces before line continuations
+ $done = ''; $this = ''; $todo = $spec;
+ while ($todo =~ m/[ \t]{2,}\\[ \t]*\r?\n/s) {
+ $done .= $`; $this = $&; $todo = $';
+ &lint_warning($file, $done, $this, "multiple leading whitespace before line
continuation (expected just a single space)");
+ $done .= $this;
+ }
+
+ # check for leading tabs
+ $done = ''; $this = ''; $todo = $spec;
+ while ($todo =~ m/^ *\t+ *[^ \t]/m) {
+ $done .= $`; $this = $&; $todo = $';
+ &lint_warning($file, $done, $this, "leading tabs (expected spaces)");
+ $done .= $this;
+ }
+
+ # check for mandatory/wished trailing blank line
+ if ($spec !~ m|\n\n$|) {
+ &lint_warning($file, $done, "", "mandatory/wished trailing blank line
missing (expected one)");
+ }
+}
+
+## _________________________________________________________________
+##
+## CHECK "comment": sharp-comments
+## _________________________________________________________________
+##
+
+sub check_comment {
+ my ($file, $spec) = @_;
+
+ # check "shebang" header
+ my $re = "";
+ $re .= '[EMAIL PROTECTED]@/lib/openpkg/bash @l_prefix@/etc/rc\\n';
+ if ($spec !~ m|^$re|os) {
+ &lint_warning($file, "", "", "invalid shebang header (expected $re)");
+ }
+
+ # check for comment indentation
+ my $done .= $`; my $this = $&; my $todo = $';
+ while ($todo =~ m/^([ \t]*)(#+)([ \t]*)(.*?)$/m) {
+ $done .= $`; $this = $&; $todo = $';
+ my ($lead, $sharp, $pad, $text) = ($1, $2, $3, $4);
+ if (length($lead) % 2 != 0) {
+ &lint_warning($file, $done, $this, "incorrect comment indentation
(expected a multiple of 2 spaces)");
+ }
+ if (length($lead) > 1 && length($sharp) > 1) {
+ &lint_warning($file, $done, $this, "indented comment has introduced
with multiple sharps (expected single sharp character)");
+ }
+ if (length($pad.$text) > 0 && length($sharp.$pad) % 4 != 0) {
+ &lint_warning($file, $done, $this, "incorrect comment text padding
(expected a multiple of 4 sharps or spaces)");
+ }
+ if (length($pad) == 0 && length($text) > 0) {
+ &lint_warning($file, $done, $this, "missing leading space before
comment text (expected padding spaces)");
+ }
+ if (length($pad) > 0 && length($text) == 0) {
+ &lint_warning($file, $done, $this, "empty comment text (expected a
reasonable text)");
+ }
+ $done .= $this;
+ }
+}
+
@@ .
______________________________________________________________________
The OpenPKG Project www.openpkg.org
CVS Repository Commit List [EMAIL PROTECTED]