#!/usr/bin/perl -w# (c) 2001, Dave Jones. (the file handling bit)# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)# (c) 2008-2010 Andy Whitcroft <apw@canonical.com># Licensed under the terms of the GNU GPL License version 2 use strict; my $P = $0;$P =~ s@.*/@@g; my $V = '0.32'; use Getopt::Long qw(:config no_auto_abbrev); my $quiet = 0;my $tree = 1;my $chk_signoff = 1;my $chk_patch = 1;my $tst_only;my $emacs = 0;my $terse = 0;my $file = 0;my $check = 0;my $summary = 1;my $mailback = 0;my $summary_file = 0;my $show_types = 0;my $root;my %debug;my %ignore_type = ();my @ignore = ();my $help = 0;my $configuration_file = ".checkpatch.conf"; sub help { my ($exitcode) = @_; print << "EOM";Usage: $P [OPTION]... [FILE]...Version: $V Options: -q, --quiet quiet --no-tree run without a kernel tree --no-signoff do not check for 'Signed-off-by' line --patch treat FILE as patchfile (default) --emacs emacs compile window format --terse one line per report -f, --file treat FILE as regular source file --subjective, --strict enable more subjective tests --ignore TYPE(,TYPE2...) ignore various comma separated message types --show-types show the message "types" in the output --root=PATH PATH to the kernel tree root --no-summary suppress the per-file summary --mailback only produce a report in case of warnings/errors --summary-file include the filename in summary --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of 'values', 'possible', 'type', and 'attr' (default is all off) --test-only=WORD report only warnings/errors containing WORD literally -h, --help, --version display this help and exit When FILE is - read standard input.EOM exit($exitcode);} my $conf = which_conf($configuration_file);if (-f $conf) { my @conf_args; open(my $conffile, '<', "$conf") or warn "$P: Can't find a readable $configuration_file file $!\n"; while (<$conffile>) { my $line = $_; $line =~ s/\s*\n?$//g; $line =~ s/^\s*//g; $line =~ s/\s+/ /g; next if ($line =~ m/^\s*#/); next if ($line =~ m/^\s*$/); my @words = split(" ", $line); foreach my $word (@words) { last if ($word =~ m/^#/); push (@conf_args, $word); } } close($conffile); unshift(@ARGV, @conf_args) if @conf_args;} GetOptions( 'q|quiet+' => \$quiet, 'tree!' => \$tree, 'signoff!' => \$chk_signoff, 'patch!' => \$chk_patch, 'emacs!' => \$emacs, 'terse!' => \$terse, 'f|file!' => \$file, 'subjective!' => \$check, 'strict!' => \$check, 'ignore=s' => \@ignore, 'show-types!' => \$show_types, 'root=s' => \$root, 'summary!' => \$summary, 'mailback!' => \$mailback, 'summary-file!' => \$summary_file, 'debug=s' => \%debug, 'test-only=s' => \$tst_only, 'h|help' => \$help, 'version' => \$help) or help(1); help(0) if ($help); my $exit = 0; if ($#ARGV < 0) { print "$P: no input files\n"; exit(1);} @ignore = split(/,/, join(',',@ignore));foreach my $word (@ignore) { $word =~ s/\s*\n?$//g; $word =~ s/^\s*//g; $word =~ s/\s+/ /g; $word =~ tr/[a-z]/[A-Z]/; next if ($word =~ m/^\s*#/); next if ($word =~ m/^\s*$/); $ignore_type{$word}++;} my $dbg_values = 0;my $dbg_possible = 0;my $dbg_type = 0;my $dbg_attr = 0;for my $key (keys %debug) { ## no critic eval "\${dbg_$key} = '$debug{$key}';"; die "$@" if ($@);} my $rpt_cleaners = 0; if ($terse) { $emacs = 1; $quiet++;} if ($tree) { if (defined $root) { if (!top_of_kernel_tree($root)) { die "$P: $root: --root does not point at a valid tree\n"; } } else { if (top_of_kernel_tree('.')) { $root = '.'; } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && top_of_kernel_tree($1)) { $root = $1; } } if (!defined $root) { print "Must be run from the top-level dir. of a kernel tree\n"; exit(2); }} my $emitted_corrupt = 0; our $Ident = qr{ [A-Za-z_][A-Za-z\d_]* (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* }x;our $Storage = qr{extern|static|asmlinkage};our $Sparse = qr{ __user| __kernel| __force| __iomem| __must_check| __init_refok| __kprobes| __ref| __rcu }x; # Notes to $Attribute:# We need \b after 'init' otherwise 'initconst' will cause a false positive in a checkour $Attribute = qr{ const| __percpu| __nocast| __safe| __bitwise__| __packed__| __packed2__| __naked| __maybe_unused| __always_unused| __noreturn| __used| __cold| __noclone| __deprecated| __read_mostly| __kprobes| __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| ____cacheline_aligned| ____cacheline_aligned_in_smp| ____cacheline_internodealigned_in_smp| __weak }x;our $Modifier;our $Inline = qr{inline|__always_inline|noinline};our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};our $Lval = qr{$Ident(?:$Member)*}; our $Constant = qr{(?i:(?:[0-9]+|0x[0-9a-f]+)[ul]*)};our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};our $Compare = qr{<=|>=|==|!=|<|>};our $Operators = qr{ <=|>=|==|!=| =>|->|<<|>>|<|>|!|~| &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|% }x; our $NonptrType;our $Type;our $Declare; our $NON_ASCII_UTF8 = qr{ [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16}x; our $UTF8 = qr{ [\x09\x0A\x0D\x20-\x7E] # ASCII | $NON_ASCII_UTF8}x; our $typeTypedefs = qr{(?x: (?:__)?(?:u|s|be|le)(?:8|16|32|64)| atomic_t)}; our $logFunctions = qr{(?x: printk(?:_ratelimited|_once|)| [a-z0-9]+_(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| WARN(?:_RATELIMIT|_ONCE|)| panic| MODULE_[A-Z_]+)}; our $signature_tags = qr{(?xi: Signed-off-by:| Acked-by:| Tested-by:| Reviewed-by:| Reported-by:| To:| Cc:)}; our @typeList = ( qr{void}, qr{(?:unsigned\s+)?char}, qr{(?:unsigned\s+)?short}, qr{(?:unsigned\s+)?int}, qr{(?:unsigned\s+)?long}, qr{(?:unsigned\s+)?long\s+int}, qr{(?:unsigned\s+)?long\s+long}, qr{(?:unsigned\s+)?long\s+long\s+int}, qr{unsigned}, qr{float}, qr{double}, qr{bool}, qr{struct\s+$Ident}, qr{union\s+$Ident}, qr{enum\s+$Ident}, qr{${Ident}_t}, qr{${Ident}_handler}, qr{${Ident}_handler_fn},);our @modifierList = ( qr{fastcall},); our $allowed_asm_includes = qr{(?x: irq| memory)};# memory.h: ARM has a custom one sub build_types { my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; $NonptrType = qr{ (?:$Modifier\s+|const\s+)* (?: (?:typeof|__typeof__)\s*\([^\)]*\)| (?:$typeTypedefs\b)| (?:${all}\b) ) (?:\s+$Modifier|\s+const)* }x; $Type = qr{ $NonptrType (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? (?:\s+$Inline|\s+$Modifier)* }x; $Declare = qr{(?:$Storage\s+)?$Type};}build_types(); our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; # Using $balanced_parens, $LvalOrFunc, or $FuncArg# requires at least perl version v5.10.0# Any use must be runtime checked with $^V our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/;our $LvalOrFunc = qr{($Lval)\s*($balanced_parens{0,1})\s*};our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)}; sub deparenthesize { my ($string) = @_; return "" if (!defined($string)); $string =~ s@^\s*\(\s*@@g; $string =~ s@\s*\)\s*$@@g; $string =~ s@\s+@ @g; return $string;} $chk_signoff = 0 if ($file); my @dep_includes = ();my @dep_functions = ();my $removal = "Documentation/feature-removal-schedule.txt";if ($tree && -f "$root/$removal") { open(my $REMOVE, '<', "$root/$removal") || die "$P: $removal: open failed - $!\n"; while (<$REMOVE>) { if (/^Check:\s+(.*\S)/) { for my $entry (split(/[, ]+/, $1)) { if ($entry =~ m@include/(.*)@) { push(@dep_includes, $1); } elsif ($entry !~ m@/@) { push(@dep_functions, $entry); } } } } close($REMOVE);} my @rawlines = ();my @lines = ();my $vname;for my $filename (@ARGV) { my $FILE; if ($file) { open($FILE, '-|', "diff -u /dev/null $filename") || die "$P: $filename: diff failed - $!\n"; } elsif ($filename eq '-') { open($FILE, '<&STDIN'); } else { open($FILE, '<', "$filename") || die "$P: $filename: open failed - $!\n"; } if ($filename eq '-') { $vname = 'Your patch'; } else { $vname = $filename; } while (<$FILE>) { chomp; push(@rawlines, $_); } close($FILE); if (!process($filename)) { $exit = 1; } @rawlines = (); @lines = ();} exit($exit); sub top_of_kernel_tree { my ($root) = @_; my @tree_check = ( "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", "README", "Documentation", "arch", "include", "drivers", "fs", "init", "ipc", "kernel", "lib", "scripts", ); foreach my $check (@tree_check) { if (! -e $root . '/' . $check) { return 0; } } return 1; } sub parse_email { my ($formatted_email) = @_; my $name = ""; my $address = ""; my $comment = ""; if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { $name = $1; $address = $2; $comment = $3 if defined $3; } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { $address = $1; $comment = $2 if defined $2; } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { $address = $1; $comment = $2 if defined $2; $formatted_email =~ s/$address.*$//; $name = $formatted_email; $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; # If there's a name left after stripping spaces and # leading quotes, and the address doesn't have both # leading and trailing angle brackets, the address # is invalid. ie: # "joe smith joe@smith.com" bad # "joe smith <joe@smith.com" bad if ($name ne "" && $address !~ /^<[^>]+>$/) { $name = ""; $address = ""; $comment = ""; } } $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; $address =~ s/^\s+|\s+$//g; $address =~ s/^\<|\>$//g; if ($name =~ /[^\w \-]/i) { ##has "must quote" chars $name =~ s/(?<!\\)"/\\"/g; ##escape quotes $name = "\"$name\""; } return ($name, $address, $comment);} sub format_email { my ($name, $address) = @_; my $formatted_email; $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; $address =~ s/^\s+|\s+$//g; if ($name =~ /[^\w \-]/i) { ##has "must quote" chars $name =~ s/(?<!\\)"/\\"/g; ##escape quotes $name = "\"$name\""; } if ("$name" eq "") { $formatted_email = "$address"; } else { $formatted_email = "$name <$address>"; } return $formatted_email;} sub which_conf { my ($conf) = @_; foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { if (-e "$path/$conf") {Lines 1–500 of 3546. Load more
#!/usr/bin/perl -w # (c) 2001, Dave Jones. (the file handling bit) # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit) # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite) # (c) 2008-2010 Andy Whitcroft <apw@canonical.com> # Licensed under the terms of the GNU GPL License version 2 use strict; my $P = $0; $P =~ s@.*/@@g; my $V = '0.32'; use Getopt::Long qw(:config no_auto_abbrev); my $quiet = 0; my $tree = 1; my $chk_signoff = 1; my $chk_patch = 1; my $tst_only; my $emacs = 0; my $terse = 0; my $file = 0; my $check = 0; my $summary = 1; my $mailback = 0; my $summary_file = 0; my $show_types = 0; my $root; my %debug; my %ignore_type = (); my @ignore = (); my $help = 0; my $configuration_file = ".checkpatch.conf"; sub help { my ($exitcode) = @_; print << "EOM"; Usage: $P [OPTION]... [FILE]... Version: $V Options: -q, --quiet quiet --no-tree run without a kernel tree --no-signoff do not check for 'Signed-off-by' line --patch treat FILE as patchfile (default) --emacs emacs compile window format --terse one line per report -f, --file treat FILE as regular source file --subjective, --strict enable more subjective tests --ignore TYPE(,TYPE2...) ignore various comma separated message types --show-types show the message "types" in the output --root=PATH PATH to the kernel tree root --no-summary suppress the per-file summary --mailback only produce a report in case of warnings/errors --summary-file include the filename in summary --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of 'values', 'possible', 'type', and 'attr' (default is all off) --test-only=WORD report only warnings/errors containing WORD literally -h, --help, --version display this help and exit When FILE is - read standard input. EOM exit($exitcode); } my $conf = which_conf($configuration_file); if (-f $conf) { my @conf_args; open(my $conffile, '<', "$conf") or warn "$P: Can't find a readable $configuration_file file $!\n"; while (<$conffile>) { my $line = $_; $line =~ s/\s*\n?$//g; $line =~ s/^\s*//g; $line =~ s/\s+/ /g; next if ($line =~ m/^\s*#/); next if ($line =~ m/^\s*$/); my @words = split(" ", $line); foreach my $word (@words) { last if ($word =~ m/^#/); push (@conf_args, $word); } } close($conffile); unshift(@ARGV, @conf_args) if @conf_args; } GetOptions( 'q|quiet+' => \$quiet, 'tree!' => \$tree, 'signoff!' => \$chk_signoff, 'patch!' => \$chk_patch, 'emacs!' => \$emacs, 'terse!' => \$terse, 'f|file!' => \$file, 'subjective!' => \$check, 'strict!' => \$check, 'ignore=s' => \@ignore, 'show-types!' => \$show_types, 'root=s' => \$root, 'summary!' => \$summary, 'mailback!' => \$mailback, 'summary-file!' => \$summary_file, 'debug=s' => \%debug, 'test-only=s' => \$tst_only, 'h|help' => \$help, 'version' => \$help ) or help(1); help(0) if ($help); my $exit = 0; if ($#ARGV < 0) { print "$P: no input files\n"; exit(1); } @ignore = split(/,/, join(',',@ignore)); foreach my $word (@ignore) { $word =~ s/\s*\n?$//g; $word =~ s/^\s*//g; $word =~ s/\s+/ /g; $word =~ tr/[a-z]/[A-Z]/; next if ($word =~ m/^\s*#/); next if ($word =~ m/^\s*$/); $ignore_type{$word}++; } my $dbg_values = 0; my $dbg_possible = 0; my $dbg_type = 0; my $dbg_attr = 0; for my $key (keys %debug) { ## no critic eval "\${dbg_$key} = '$debug{$key}';"; die "$@" if ($@); } my $rpt_cleaners = 0; if ($terse) { $emacs = 1; $quiet++; } if ($tree) { if (defined $root) { if (!top_of_kernel_tree($root)) { die "$P: $root: --root does not point at a valid tree\n"; } } else { if (top_of_kernel_tree('.')) { $root = '.'; } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ && top_of_kernel_tree($1)) { $root = $1; } } if (!defined $root) { print "Must be run from the top-level dir. of a kernel tree\n"; exit(2); } } my $emitted_corrupt = 0; our $Ident = qr{ [A-Za-z_][A-Za-z\d_]* (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)* }x; our $Storage = qr{extern|static|asmlinkage}; our $Sparse = qr{ __user| __kernel| __force| __iomem| __must_check| __init_refok| __kprobes| __ref| __rcu }x; # Notes to $Attribute: # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check our $Attribute = qr{ const| __percpu| __nocast| __safe| __bitwise__| __packed__| __packed2__| __naked| __maybe_unused| __always_unused| __noreturn| __used| __cold| __noclone| __deprecated| __read_mostly| __kprobes| __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)| ____cacheline_aligned| ____cacheline_aligned_in_smp| ____cacheline_internodealigned_in_smp| __weak }x; our $Modifier; our $Inline = qr{inline|__always_inline|noinline}; our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]}; our $Lval = qr{$Ident(?:$Member)*}; our $Constant = qr{(?i:(?:[0-9]+|0x[0-9a-f]+)[ul]*)}; our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)}; our $Compare = qr{<=|>=|==|!=|<|>}; our $Operators = qr{ <=|>=|==|!=| =>|->|<<|>>|<|>|!|~| &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|% }x; our $NonptrType; our $Type; our $Declare; our $NON_ASCII_UTF8 = qr{ [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 }x; our $UTF8 = qr{ [\x09\x0A\x0D\x20-\x7E] # ASCII | $NON_ASCII_UTF8 }x; our $typeTypedefs = qr{(?x: (?:__)?(?:u|s|be|le)(?:8|16|32|64)| atomic_t )}; our $logFunctions = qr{(?x: printk(?:_ratelimited|_once|)| [a-z0-9]+_(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)| WARN(?:_RATELIMIT|_ONCE|)| panic| MODULE_[A-Z_]+ )}; our $signature_tags = qr{(?xi: Signed-off-by:| Acked-by:| Tested-by:| Reviewed-by:| Reported-by:| To:| Cc: )}; our @typeList = ( qr{void}, qr{(?:unsigned\s+)?char}, qr{(?:unsigned\s+)?short}, qr{(?:unsigned\s+)?int}, qr{(?:unsigned\s+)?long}, qr{(?:unsigned\s+)?long\s+int}, qr{(?:unsigned\s+)?long\s+long}, qr{(?:unsigned\s+)?long\s+long\s+int}, qr{unsigned}, qr{float}, qr{double}, qr{bool}, qr{struct\s+$Ident}, qr{union\s+$Ident}, qr{enum\s+$Ident}, qr{${Ident}_t}, qr{${Ident}_handler}, qr{${Ident}_handler_fn}, ); our @modifierList = ( qr{fastcall}, ); our $allowed_asm_includes = qr{(?x: irq| memory )}; # memory.h: ARM has a custom one sub build_types { my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)"; my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)"; $Modifier = qr{(?:$Attribute|$Sparse|$mods)}; $NonptrType = qr{ (?:$Modifier\s+|const\s+)* (?: (?:typeof|__typeof__)\s*\([^\)]*\)| (?:$typeTypedefs\b)| (?:${all}\b) ) (?:\s+$Modifier|\s+const)* }x; $Type = qr{ $NonptrType (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*|\[\])+|(?:\s*\[\s*\])+)? (?:\s+$Inline|\s+$Modifier)* }x; $Declare = qr{(?:$Storage\s+)?$Type}; } build_types(); our $Typecast = qr{\s*(\(\s*$NonptrType\s*\)){0,1}\s*}; # Using $balanced_parens, $LvalOrFunc, or $FuncArg # requires at least perl version v5.10.0 # Any use must be runtime checked with $^V our $balanced_parens = qr/(\((?:[^\(\)]++|(?-1))*\))/; our $LvalOrFunc = qr{($Lval)\s*($balanced_parens{0,1})\s*}; our $FuncArg = qr{$Typecast{0,1}($LvalOrFunc|$Constant)}; sub deparenthesize { my ($string) = @_; return "" if (!defined($string)); $string =~ s@^\s*\(\s*@@g; $string =~ s@\s*\)\s*$@@g; $string =~ s@\s+@ @g; return $string; } $chk_signoff = 0 if ($file); my @dep_includes = (); my @dep_functions = (); my $removal = "Documentation/feature-removal-schedule.txt"; if ($tree && -f "$root/$removal") { open(my $REMOVE, '<', "$root/$removal") || die "$P: $removal: open failed - $!\n"; while (<$REMOVE>) { if (/^Check:\s+(.*\S)/) { for my $entry (split(/[, ]+/, $1)) { if ($entry =~ m@include/(.*)@) { push(@dep_includes, $1); } elsif ($entry !~ m@/@) { push(@dep_functions, $entry); } } } } close($REMOVE); } my @rawlines = (); my @lines = (); my $vname; for my $filename (@ARGV) { my $FILE; if ($file) { open($FILE, '-|', "diff -u /dev/null $filename") || die "$P: $filename: diff failed - $!\n"; } elsif ($filename eq '-') { open($FILE, '<&STDIN'); } else { open($FILE, '<', "$filename") || die "$P: $filename: open failed - $!\n"; } if ($filename eq '-') { $vname = 'Your patch'; } else { $vname = $filename; } while (<$FILE>) { chomp; push(@rawlines, $_); } close($FILE); if (!process($filename)) { $exit = 1; } @rawlines = (); @lines = (); } exit($exit); sub top_of_kernel_tree { my ($root) = @_; my @tree_check = ( "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile", "README", "Documentation", "arch", "include", "drivers", "fs", "init", "ipc", "kernel", "lib", "scripts", ); foreach my $check (@tree_check) { if (! -e $root . '/' . $check) { return 0; } } return 1; } sub parse_email { my ($formatted_email) = @_; my $name = ""; my $address = ""; my $comment = ""; if ($formatted_email =~ /^(.*)<(\S+\@\S+)>(.*)$/) { $name = $1; $address = $2; $comment = $3 if defined $3; } elsif ($formatted_email =~ /^\s*<(\S+\@\S+)>(.*)$/) { $address = $1; $comment = $2 if defined $2; } elsif ($formatted_email =~ /(\S+\@\S+)(.*)$/) { $address = $1; $comment = $2 if defined $2; $formatted_email =~ s/$address.*$//; $name = $formatted_email; $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; # If there's a name left after stripping spaces and # leading quotes, and the address doesn't have both # leading and trailing angle brackets, the address # is invalid. ie: # "joe smith joe@smith.com" bad # "joe smith <joe@smith.com" bad if ($name ne "" && $address !~ /^<[^>]+>$/) { $name = ""; $address = ""; $comment = ""; } } $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; $address =~ s/^\s+|\s+$//g; $address =~ s/^\<|\>$//g; if ($name =~ /[^\w \-]/i) { ##has "must quote" chars $name =~ s/(?<!\\)"/\\"/g; ##escape quotes $name = "\"$name\""; } return ($name, $address, $comment); } sub format_email { my ($name, $address) = @_; my $formatted_email; $name =~ s/^\s+|\s+$//g; $name =~ s/^\"|\"$//g; $address =~ s/^\s+|\s+$//g; if ($name =~ /[^\w \-]/i) { ##has "must quote" chars $name =~ s/(?<!\\)"/\\"/g; ##escape quotes $name = "\"$name\""; } if ("$name" eq "") { $formatted_email = "$address"; } else { $formatted_email = "$name <$address>"; } return $formatted_email; } sub which_conf { my ($conf) = @_; foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) { if (-e "$path/$conf") {