Skip to content

Commit

Permalink
Add diff-filter.
Browse files Browse the repository at this point in the history
  • Loading branch information
caladri committed Sep 3, 2011
1 parent a1c313b commit 4ba5211
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
SUBDIR+=
SUBDIR+=bin

.include <bsd.subdir.mk>
2 changes: 2 additions & 0 deletions Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
WARNS?= 6
WFORMAT?= 1
3 changes: 3 additions & 0 deletions bin/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
SUBDIR+=diff-filter

.include <bsd.subdir.mk>
3 changes: 3 additions & 0 deletions bin/Makefile.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#

.include "${.CURDIR}/../../Makefile.inc"
4 changes: 4 additions & 0 deletions bin/diff-filter/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PROG= diff-filter
MAN=

.include "${.CURDIR}/../../mk/bsdplus.prog.mk"
176 changes: 176 additions & 0 deletions bin/diff-filter/diff-filter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#include <err.h>
#include <errno.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

enum rule_type {
AllowRule,
DenyRule,
};

struct rule {
enum rule_type r_type;
regex_t r_regex;
struct rule *r_next;
};

static int diff_filter(FILE *, enum rule_type, struct rule *);
static int diff_filter_file(const char *, enum rule_type, struct rule *);
static struct rule *rule_add(struct rule *, enum rule_type, const char *);
static enum rule_type rules_run(const char *, enum rule_type, struct rule *);
static void usage(void);

int
main(int argc, char *argv[])
{
enum rule_type default_rule;
struct rule *rules;
const char *file;
int error;
int ch;

default_rule = AllowRule;
rules = NULL;

while ((ch = getopt(argc, argv, "ADa:d:")) != -1) {
switch (ch) {
case 'A':
default_rule = AllowRule;
break;
case 'D':
default_rule = DenyRule;
break;
case 'a':
rules = rule_add(rules, AllowRule, optarg);
break;
case 'd':
rules = rule_add(rules, DenyRule, optarg);
break;
default:
usage();
}
}
argc -= optind;
argv += optind;

if (argc == 0) {
error = diff_filter(stdin, default_rule, rules);
if (error != 0)
errc(1, error, "diff_filter");
} else {
int errors;

errors = 0;

while (argc--) {
file = *argv++;
error = diff_filter_file(file, default_rule, rules);
if (error != 0) {
warnc(error, "diff_filter(%s)", file);
errors++;
}
}
if (errors > 0)
errx(1, "%u files had errors", errors);
}

return (0);
}

static int
diff_filter(FILE *file, enum rule_type default_rule, struct rule *rules)
{
enum rule_type state;
char *line;
size_t len;

state = default_rule;

while ((line = fgetln(file, &len)) != NULL) {
if (len == 0)
continue;
line[len - 1] = '\0';

if (strncmp(line, "Index: ", 7) == 0)
state = rules_run(line + 7, default_rule, rules);

if (state == AllowRule)
fprintf(stdout, "%s\n", line);
}
if (ferror(file)) {
if (errno == 0)
return (EIO);
return (errno);
}

return (0);
}

static int
diff_filter_file(const char *name, enum rule_type default_rule, struct rule *rules)
{
FILE *file;
int error;

file = fopen(name, "r");
if (file == NULL)
return (errno);

error = diff_filter(file, default_rule, rules);

fclose(file);

return (error);
}

static struct rule *
rule_add(struct rule *rules, enum rule_type type, const char *string)
{
struct rule *rule;
int rv;

rule = malloc(sizeof *rule);
rule->r_type = type;
rule->r_next = NULL;

rv = regcomp(&rule->r_regex, string, REG_NOSUB | REG_EXTENDED);
if (rv != 0)
err(1, "couldn't compile regex \"%s\"", string);

if (rules == NULL)
return (rule);

while (rules->r_next != NULL)
rules = rules->r_next;
rules->r_next = rule;
return (rules);
}

static enum rule_type
rules_run(const char *line, enum rule_type default_rule, struct rule *rules)
{
struct rule *rule;
int rv;

for (rule = rules; rule != NULL; rule = rule->r_next) {
rv = regexec(&rule->r_regex, line, 0, NULL, 0);
if (rv == 0)
return (rule->r_type);
if (rv == REG_NOMATCH)
continue;
errx(1, "regexec failed: %d", rv);
}

return (default_rule);
}

static void
usage(void)
{
fprintf(stderr,
"diff-filter [-A | -D] [-a allow_regex] [-d deny_regex] file ...\n");
exit(1);
}
6 changes: 6 additions & 0 deletions mk/bsdplus.prog.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.include <bsd.prog.mk>

OSNAME!=uname
.if ${OSNAME} == "Darwin"
CFLAGS:=${CFLAGS:N-Wsystem-headers}
.endif

0 comments on commit 4ba5211

Please sign in to comment.