pbot/modules/codepad.pl

157 lines
3.6 KiB
Perl
Raw Normal View History

2010-03-28 16:34:43 +02:00
#!/usr/bin/perl
use warnings;
use strict;
use LWP::UserAgent;
use URI::Escape;
use HTML::Entities;
use HTML::Parse;
use HTML::FormatText;
use IPC::Open2;
use Text::Balanced qw(extract_codeblock);
2010-03-28 16:34:43 +02:00
2010-04-05 13:29:49 +02:00
my @languages = qw/C C++ D Haskell Lua OCaml PHP Perl Python Ruby Scheme Tcl/;
my %preludes = ( 'C' => "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n",
2010-04-05 13:36:19 +02:00
'C++' => "#include <iostream>\n#include <cstdio>\n",
2010-04-05 13:29:49 +02:00
);
2010-03-28 16:34:43 +02:00
if($#ARGV <= 0) {
2010-04-10 00:53:55 +02:00
print "Usage: cc [-lang=<language>] <code>\n";
2010-03-28 16:34:43 +02:00
exit 0;
}
my $nick = shift @ARGV;
my $code = join ' ', @ARGV;
my $output;
2010-03-28 16:34:43 +02:00
2010-04-05 13:29:49 +02:00
open FILE, ">> codepad_log.txt";
print FILE "$nick: $code\n";
2010-03-28 16:34:43 +02:00
my $lang = "C";
$lang = $1 if $code =~ s/-lang=([^\b\s]+)//i;
my $show_url = 0;
$show_url = 1 if $code =~ s/-showurl//i;
2010-03-28 17:06:50 +02:00
my $found = 0;
foreach my $l (@languages) {
if(uc $lang eq uc $l) {
$lang = $l;
$found = 1;
last;
}
}
if(not $found) {
print "$nick: Invalid language '$lang'. Supported languages are: @languages\n";
exit 0;
}
2010-03-28 16:34:43 +02:00
my $ua = LWP::UserAgent->new();
$ua->agent("Mozilla/5.0");
push @{ $ua->requests_redirectable }, 'POST';
2010-04-05 13:29:49 +02:00
$code =~ s/#include <([^>]+)>/\n#include <$1>\n/g;
$code =~ s/#([^ ]+) (.*?)\\n/\n#$1 $2\n/g;
$code =~ s/#([\w\d_]+)\\n/\n#$1\n/g;
2010-03-28 20:37:53 +02:00
my $precode = $preludes{$lang} . $code;
$code = '';
2010-03-28 16:34:43 +02:00
if($lang eq "C" or $lang eq "C++") {
my $has_main = 0;
2010-04-05 13:29:49 +02:00
my $prelude = '';
$prelude = "$1$2" if $precode =~ s/^\s*(#.*)(#.*?[>\n])//s;
while($precode =~ s/([ a-zA-Z0-9_*\[\]]+)\s+([a-zA-Z0-9_*]+)\s*\((.*?)\)\s*({.*)//) {
my ($ret, $ident, $params, $potential_body) = ($1, $2, $3, $4);
my @extract = extract_codeblock($potential_body, '{}');
my $body;
if(not defined $extract[0]) {
$output .= "<pre>error: unmatched brackets for function '$ident'; </pre>";
$body = $extract[1];
} else {
$body = $extract[0];
$precode .= $extract[1];
}
$code .= "$ret $ident($params) $body\n\n";
$has_main = 1 if $ident eq 'main';
}
$precode =~ s/^\s+//;
$precode =~ s/\s+$//;
if(not $has_main) {
$code = "$prelude\n\n$code\n\nint main(int argc, char **argv) { $precode\n;\n return 0;}\n";
} else {
$code = "$prelude\n\n$precode\n\n$code\n";
}
} else {
$code = $precode;
2010-04-05 13:29:49 +02:00
}
2010-03-28 16:34:43 +02:00
if($lang eq "C" or $lang eq "C++") {
$code = pretty($code);
}
2010-03-28 16:34:43 +02:00
my %post = ( 'lang' => $lang, 'code' => $code, 'private' => 'True', 'run' => 'True', 'submit' => 'Submit' );
my $response = $ua->post("http://codepad.org", \%post);
if(not $response->is_success) {
print "There was an error compiling the code.\n";
die $response->status_line;
}
my $text = $response->decoded_content;
2010-04-05 13:29:49 +02:00
my $url = $response->request->uri;
2010-03-28 16:34:43 +02:00
2010-04-05 13:29:49 +02:00
# remove line numbers
2010-03-28 16:34:43 +02:00
$text =~ s/<a style="" name="output-line-\d+">\d+<\/a>//g;
if($text =~ /<span class="heading">Output:<\/span>.+?<div class="code">(.*)<\/div>.+?<\/table>/si) {
$output .= "$1";
2010-03-28 16:34:43 +02:00
} else {
$output .= "<pre>No output.</pre>";
2010-03-28 16:34:43 +02:00
}
$output = decode_entities($output);
$output = HTML::FormatText->new->format(parse_html($output));
2010-04-26 01:24:47 +02:00
$output =~ s/^\s+//;
2010-03-28 16:34:43 +02:00
$output =~ s/\s*Line\s+\d+\s+://g;
2010-03-28 17:16:34 +02:00
$output =~ s/ \(first use in this function\)//g;
$output =~ s/error: \(Each undeclared identifier is reported only once.*?\)//g;
2010-04-26 01:24:47 +02:00
$output =~ s/error: (.*?).error/error: $1; error/g;
2010-03-28 17:16:34 +02:00
print FILE localtime() . "\n";
2010-04-10 00:53:55 +02:00
print FILE "$nick: [ $url ] $output\n\n";
2010-04-05 13:29:49 +02:00
close FILE;
if($show_url) {
print "$nick: [ $url ] $output\n";
} else {
print "$nick: $output\n";
}
sub pretty {
my $code = join '', @_;
my $result;
my $pid = open2(\*IN, \*OUT, 'astyle -Upf');
2010-04-28 00:57:34 +02:00
print OUT "$code\n";
close OUT;
while(my $line = <IN>) {
$result .= $line;
}
close IN;
waitpid($pid, 0);
return $result;
}
2010-04-05 13:29:49 +02:00