[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Question about POSIX regex support

From: James Youngman
Subject: Re: Question about POSIX regex support
Date: Fri, 22 Jun 2007 09:57:26 +0100

On 6/22/07, Bruno Haible <address@hidden> wrote:
  3) Verify that every source file that includes gnulib headers starts out
     with   #include <config.h>.

Here's a quick way of doing that (derived from the coreutils Makefile.maint) :-

#! /usr/bin/env python

import re
import sys

FIRST_INCLUDE = 'config.h'
problems = 0

   [r'(?<!\w)free \(\(', "don't cast the argument to free()"],
   [r'\*\) *x(m|c|re)alloc(?!\w)',"don't cast the result of x*alloc"],
   [r'\*\) *alloca(?!\w)',"don't cast the result of alloca"],
   [r'[ ]       ',"found SPACE-TAB; remove the space"],
    'do not use *scan''f, ato''f, ato''i, ato''l, ato''ll, ato''q, or
   [r'error \(EXIT_SUCCESS',"passing EXIT_SUCCESS to error is confusing"],
   [r'file[s]ystem', "prefer writing 'file system' to 'filesystem'"],
   [r'HAVE''_CONFIG_H', "Avoid checking HAVE_CONFIG_H"],
#   [r'HAVE_FCNTL_H', "Avoid checking HAVE_FCNTL_H"],
   [r'O_NDELAY', "Avoid using O_NDELAY"],
   [r'the *the', "'the the' is probably not deliberate"],
   [r'(?<!\w)error \([^_"]*[^_]"[^"]*[a-z]{3}', "untranslated error message"],
   [r'^# *if\s+defined *\(', "useless parentheses in '#if defined'"],


   [r'# *include <assert.h>(?!.*assert \()',
    "If you include <assert.h>, use assert()."],
   [r'# *include "quotearg.h"(?!.*(?<!\w)quotearg(_[^ ]+)? \()',
    "If you include \"quotearg.h\", use one of its functions."],
   [r'# *include "quote.h"(?!.*(?<!\w)quote(_[^ ]+)? \()',
    "If you include \"quote.h\", use one of its functions."],
   [r'\s$', "trailing whitespace"],

# missing check: ChangeLog prefixes
# missing: sc_always_defined_macros from coreutils
# missing: sc_tight_scope

COMPILED_LINE_SMELLS = [(re.compile(pong[0]), pong[1])
                       for pong in LINE_SMELLS_SRC]
COMPILED_FILE_SMELLS = [(re.compile(pong[0], re.DOTALL), pong[1])
                       for pong in FILE_SMELLS_SRC]

def Problem(filename, desc):
   global problems
   print >> sys.stderr, "error: %s: %s" % (filename, desc)
   problems += 1

def Warning(filename, desc):
   print >> sys.stderr, "warning: %s: %s" % (filename, desc)

def BuildIncludeList(text):
   include_re = re.compile(r'# *include +[<"](.*)[>"]')
   return [m.group(1) for m in include_re.finditer(text)]

def CheckFirstInclude(filename, lines, fulltext):
   includes = BuildIncludeList(fulltext)
   if includes and includes[0] != FIRST_INCLUDE:
       if FIRST_INCLUDE in includes:
           fmt = "%s is first include file, but %s should be included first"
           Problem(filename, fmt % (includes[0], FIRST_INCLUDE))
   if FIRST_INCLUDE not in includes:
               "%s should be included by most files" % FIRST_INCLUDE)

def CheckLineSmells(filename, lines, fulltext):
   for line in lines:
       for smell in COMPILED_LINE_SMELLS:
           match = smell[0].search(line[1])
           if match:
               Problem(filename, '%d: "%s": %s'
                       % (line[0], match.group(0), smell[1]))

def CheckFileSmells(filename, lines, fulltext):
   for smell in COMPILED_FILE_SMELLS:
       match = smell[0].search(fulltext)
       if match:
           Problem(filename, ' %s' % (smell[1],))

def SniffSourceFile(filename, lines, fulltext):
   for sniffer in [CheckFirstInclude, CheckLineSmells, CheckFileSmells]:
       sniffer(filename, lines, fulltext)

def main(args):
   "main program"
   for srcfile in args[1:]:
       f = open(srcfile)
       line_number = 1
       lines = []
       for line in f.readlines():
           lines.append( (line_number, line) )
           line_number += 1
       fulltext = '\n'.join([line[1] for line in lines])
       SniffSourceFile(srcfile, lines, fulltext)
   if problems:
       return 1
       return 0

if __name__ == "__main__":

reply via email to

[Prev in Thread] Current Thread [Next in Thread]