PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/ideone.pl

http://pbot2-pl.googlecode.com/
Perl | 799 lines | 699 code | 92 blank | 8 comment | 99 complexity | 06bb2bc25137038c47600e06d3a3fdec MD5 | raw file
Possible License(s): LGPL-2.0
  1. #!/usr/bin/perl
  2. # use warnings;
  3. use strict;
  4. use feature qw(switch);
  5. use SOAP::Lite;
  6. $SOAP::Constants::DO_NOT_USE_XML_PARSER = 1;
  7. use IPC::Open2;
  8. use HTML::Entities;
  9. use Text::Balanced qw(extract_codeblock extract_delimited);
  10. my $user = 'test';
  11. my $pass = 'test';
  12. my $soap = SOAP::Lite->new(proxy => 'http://ideone.com/api/1/service');
  13. my $result;
  14. my $MAX_UNDO_HISTORY = 100;
  15. my $output = "";
  16. my $nooutput = 'No output.';
  17. my %languages = (
  18. 'Ada' => { 'id' => '7', 'name' => 'Ada (gnat-4.3.2)' },
  19. 'asm' => { 'id' => '13', 'name' => 'Assembler (nasm-2.07)' },
  20. 'nasm' => { 'id' => '13', 'name' => 'Assembler (nasm-2.07)' },
  21. 'gas' => { 'id' => '45', 'name' => 'Assembler (gcc-4.3.4)' },
  22. 'Assembler' => { 'id' => '13', 'name' => 'Assembler (nasm-2.07)' },
  23. 'Assembler' => { 'id' => '13', 'name' => 'Assembler (nasm-2.07)' },
  24. 'gawk' => { 'id' => '104', 'name' => 'AWK (gawk) (gawk-3.1.6)' },
  25. 'mawk' => { 'id' => '105', 'name' => 'AWK (mawk) (mawk-1.3.3)' },
  26. 'Bash' => { 'id' => '28', 'name' => 'Bash (bash 4.0.35)' },
  27. 'bc' => { 'id' => '110', 'name' => 'bc (bc-1.06.95)' },
  28. 'Brainfuck' => { 'id' => '12', 'name' => 'Brainf**k (bff-1.0.3.1)' },
  29. 'bf' => { 'id' => '12', 'name' => 'Brainf**k (bff-1.0.3.1)' },
  30. 'gnu89' => { 'id' => '11', 'name' => 'C (gcc-4.3.4)' },
  31. 'C89' => { 'id' => '11', 'name' => 'C (gcc-4.3.4)' },
  32. 'C' => { 'id' => '11', 'name' => 'C (gcc-4.3.4)' },
  33. 'C#' => { 'id' => '27', 'name' => 'C# (gmcs 2.0.1)' },
  34. 'C++' => { 'id' => '1', 'name' => 'C++ (gcc-4.3.4)' },
  35. 'C99' => { 'id' => '34', 'name' => 'C99 strict (gcc-4.3.4)' },
  36. 'CLIPS' => { 'id' => '14', 'name' => 'CLIPS (clips 6.24)' },
  37. 'Clojure' => { 'id' => '111', 'name' => 'Clojure (clojure 1.1.0)' },
  38. 'COBOL' => { 'id' => '118', 'name' => 'COBOL (open-cobol-1.0)' },
  39. 'COBOL85' => { 'id' => '106', 'name' => 'COBOL 85 (tinycobol-0.65.9)' },
  40. 'clisp' => { 'id' => '32', 'name' => 'Common Lisp (clisp) (clisp 2.47)' },
  41. 'D' => { 'id' => '102', 'name' => 'D (dmd) (dmd-2.042)' },
  42. 'Erlang' => { 'id' => '36', 'name' => 'Erlang (erl-5.7.3)' },
  43. 'Forth' => { 'id' => '107', 'name' => 'Forth (gforth-0.7.0)' },
  44. 'Fortran' => { 'id' => '5', 'name' => 'Fortran (gfortran-4.3.4)' },
  45. 'Go' => { 'id' => '114', 'name' => 'Go (gc 2010-01-13)' },
  46. 'Haskell' => { 'id' => '21', 'name' => 'Haskell (ghc-6.8.2)' },
  47. 'Icon' => { 'id' => '16', 'name' => 'Icon (iconc 9.4.3)' },
  48. 'Intercal' => { 'id' => '9', 'name' => 'Intercal (c-intercal 28.0-r1)' },
  49. 'Java' => { 'id' => '10', 'name' => 'Java (sun-jdk-1.6.0.17)' },
  50. 'JS' => { 'id' => '35', 'name' => 'JavaScript (rhino) (rhino-1.6.5)' },
  51. 'JScript' => { 'id' => '35', 'name' => 'JavaScript (rhino) (rhino-1.6.5)' },
  52. 'JavaScript' => { 'id' => '35', 'name' => 'JavaScript (rhino) (rhino-1.6.5)' },
  53. 'JavaScript-rhino' => { 'id' => '35', 'name' => 'JavaScript (rhino) (rhino-1.6.5)' },
  54. 'JavaScript-spidermonkey' => { 'id' => '112', 'name' => 'JavaScript (spidermonkey) (spidermonkey-1.7)' },
  55. 'Lua' => { 'id' => '26', 'name' => 'Lua (luac 5.1.4)' },
  56. 'Nemerle' => { 'id' => '30', 'name' => 'Nemerle (ncc 0.9.3)' },
  57. 'Nice' => { 'id' => '25', 'name' => 'Nice (nicec 0.9.6)' },
  58. 'Ocaml' => { 'id' => '8', 'name' => 'Ocaml (ocamlopt 3.10.2)' },
  59. 'Pascal' => { 'id' => '22', 'name' => 'Pascal (fpc) (fpc 2.2.0)' },
  60. 'Pascal-fpc' => { 'id' => '22', 'name' => 'Pascal (fpc) (fpc 2.2.0)' },
  61. 'Pascal-gpc' => { 'id' => '2', 'name' => 'Pascal (gpc) (gpc 20070904)' },
  62. 'Perl' => { 'id' => '3', 'name' => 'Perl (perl 5.8.8)' },
  63. 'PHP' => { 'id' => '29', 'name' => 'PHP (php 5.2.11)' },
  64. 'Pike' => { 'id' => '19', 'name' => 'Pike (pike 7.6.86)' },
  65. 'Prolog' => { 'id' => '108', 'name' => 'Prolog (gnu) (gprolog-1.3.1)' },
  66. 'Prolog-gnu' => { 'id' => '108', 'name' => 'Prolog (gnu) (gprolog-1.3.1)' },
  67. 'Prolog-swi' => { 'id' => '15', 'name' => 'Prolog (swi) (swipl 5.6.64)' },
  68. 'Python' => { 'id' => '4', 'name' => 'Python (python 2.6.4)' },
  69. 'Python3' => { 'id' => '116', 'name' => 'Python3 (python-3.1.1)' },
  70. 'R' => { 'id' => '117', 'name' => 'R (R-2.9.2)' },
  71. 'Ruby' => { 'id' => '17', 'name' => 'Ruby (ruby 1.8.7)' },
  72. 'Scala' => { 'id' => '39', 'name' => 'Scala (Scalac 2.7.7)' },
  73. 'Scheme' => { 'id' => '33', 'name' => 'Scheme (guile) (guile 1.8.5)' },
  74. 'Smalltalk' => { 'id' => '23', 'name' => 'Smalltalk (gst 3.1)' },
  75. 'Tcl' => { 'id' => '38', 'name' => 'Tcl (tclsh 8.5.7)' },
  76. 'Unlambda' => { 'id' => '115', 'name' => 'Unlambda (unlambda-2.0.0)' },
  77. 'VB' => { 'id' => '101', 'name' => 'Visual Basic .NET (mono-2.4.2.3)' },
  78. );
  79. # C 11
  80. # C99 34
  81. # C++ 1
  82. my %preludes = (
  83. '34' => "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <math.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <stdint.h>\n",
  84. '11' => "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <math.h>\n#include <limits.h>\n#include <sys/types.h>\n#include <stdint.h>\n",
  85. '1' => "#include <iostream>\n#include <cstdio>\n",
  86. );
  87. if($#ARGV <= 0) {
  88. print "Usage: cc [-lang=<language>] <code>\n";
  89. exit 0;
  90. }
  91. my $nick = shift @ARGV;
  92. my $code = join ' ', @ARGV;
  93. my @last_code;
  94. if(open FILE, "< ideone_last_code.txt") {
  95. while(my $line = <FILE>) {
  96. chomp $line;
  97. push @last_code, $line;
  98. }
  99. close FILE;
  100. }
  101. if($code =~ m/^\s*show\s*$/i) {
  102. if(defined $last_code[0]) {
  103. print "$nick: $last_code[0]\n";
  104. } else {
  105. print "$nick: No recent code to show.\n"
  106. }
  107. exit 0;
  108. }
  109. my $got_run;
  110. if($code =~ m/^\s*run\s*$/i) {
  111. if(defined $last_code[0]) {
  112. $code = $last_code[0];
  113. $got_run = 1;
  114. } else {
  115. print "$nick: No recent code to run.\n";
  116. exit 0;
  117. }
  118. } else {
  119. my $subcode = $code;
  120. my $got_undo = 0;
  121. my $got_sub = 0;
  122. while($subcode =~ s/^\s*(and)?\s*undo//) {
  123. splice @last_code, 0, 1;
  124. if(not defined $last_code[0]) {
  125. print "$nick: No more undos remaining.\n";
  126. exit 0;
  127. } else {
  128. $code = $last_code[0];
  129. $got_undo = 1;
  130. }
  131. }
  132. my @replacements;
  133. my $prevchange = $last_code[0];
  134. my $got_changes = 0;
  135. while(1) {
  136. $got_sub = 0;
  137. $got_changes = 0;
  138. if($subcode =~ m/^\s*(and)?\s*remove \s*([^']+)?\s*'/) {
  139. my $modifier = 'first';
  140. $subcode =~ s/^\s*(and)?\s*//;
  141. $subcode =~ s/remove\s*([^']+)?\s*//i;
  142. $modifier = $1 if defined $1;
  143. $modifier =~ s/\s+$//;
  144. my ($e, $r) = extract_delimited($subcode, "'");
  145. my $text;
  146. if(defined $e) {
  147. $text = $e;
  148. $text =~ s/^'//;
  149. $text =~ s/'$//;
  150. $subcode = "replace $modifier '$text' with ''$r";
  151. } else {
  152. print "$nick: Unbalanced single quotes. Usage: !cc remove [all, first, .., tenth, last] 'text' [and ...]\n";
  153. exit 0;
  154. }
  155. next;
  156. }
  157. if($subcode =~ s/^\s*(and)?\s*add '//) {
  158. $subcode = "'$subcode";
  159. my ($e, $r) = extract_delimited($subcode, "'");
  160. my $text;
  161. if(defined $e) {
  162. $text = $e;
  163. $text =~ s/^'//;
  164. $text =~ s/'$//;
  165. $subcode = $r;
  166. $got_sub = 1;
  167. $got_changes = 1;
  168. if(not defined $prevchange) {
  169. print "$nick: No recent code to append to.\n";
  170. exit 0;
  171. }
  172. $code = $prevchange;
  173. $code =~ s/$/ $text/;
  174. $prevchange = $code;
  175. } else {
  176. print "$nick: Unbalanced single quotes. Usage: !cc add 'text' [and ...]\n";
  177. exit 0;
  178. }
  179. next;
  180. }
  181. if($subcode =~ m/^\s*(and)?\s*replace\s*([^']+)?\s*'.*'\s*with\s*'.*'/i) {
  182. $got_sub = 1;
  183. my $modifier = 'first';
  184. $subcode =~ s/^\s*(and)?\s*//;
  185. $subcode =~ s/replace\s*([^']+)?\s*//i;
  186. $modifier = $1 if defined $1;
  187. $modifier =~ s/\s+$//;
  188. my ($from, $to);
  189. my ($e, $r) = extract_delimited($subcode, "'");
  190. if(defined $e) {
  191. $from = $e;
  192. $from =~ s/^'//;
  193. $from =~ s/'$//;
  194. $from = quotemeta $from;
  195. $subcode = $r;
  196. $subcode =~ s/\s*with\s*//i;
  197. } else {
  198. print "$nick: Unbalanced single quotes. Usage: !cc replace 'from' with 'to' [and ...]\n";
  199. exit 0;
  200. }
  201. ($e, $r) = extract_delimited($subcode, "'");
  202. if(defined $e) {
  203. $to = $e;
  204. $to =~ s/^'//;
  205. $to =~ s/'$//;
  206. $subcode = $r;
  207. } else {
  208. print "$nick: Unbalanced single quotes. Usage: !cc replace 'from' with 'to' [and replace ... with ... [and ...]]\n";
  209. exit 0;
  210. }
  211. given($modifier) {
  212. when($_ eq 'all' ) {}
  213. when($_ eq 'last' ) {}
  214. when($_ eq 'first' ) { $modifier = 1; }
  215. when($_ eq 'second' ) { $modifier = 2; }
  216. when($_ eq 'third' ) { $modifier = 3; }
  217. when($_ eq 'fourth' ) { $modifier = 4; }
  218. when($_ eq 'fifth' ) { $modifier = 5; }
  219. when($_ eq 'sixth' ) { $modifier = 6; }
  220. when($_ eq 'seventh') { $modifier = 7; }
  221. when($_ eq 'eighth' ) { $modifier = 8; }
  222. when($_ eq 'nineth' ) { $modifier = 9; }
  223. when($_ eq 'tenth' ) { $modifier = 10; }
  224. default { print "$nick: Bad replacement modifier '$modifier'; valid modifiers are 'all', 'first', 'second', ..., 'tenth', 'last'\n"; exit 0; }
  225. }
  226. my $replacement = {};
  227. $replacement->{'from'} = $from;
  228. $replacement->{'to'} = $to;
  229. $replacement->{'modifier'} = $modifier;
  230. push @replacements, $replacement;
  231. next;
  232. }
  233. if($subcode =~ m/^\s*(and)?\s*s\/.*\//) {
  234. $got_sub = 1;
  235. $subcode =~ s/^\s*(and)?\s*s//;
  236. my ($regex, $to);
  237. my ($e, $r) = extract_delimited($subcode, '/');
  238. if(defined $e) {
  239. $regex = $e;
  240. $regex =~ s/^\///;
  241. $regex =~ s/\/$//;
  242. $subcode = "/$r";
  243. } else {
  244. print "$nick: Unbalanced slashes. Usage: !cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n";
  245. exit 0;
  246. }
  247. ($e, $r) = extract_delimited($subcode, '/');
  248. if(defined $e) {
  249. $to = $e;
  250. $to =~ s/^\///;
  251. $to =~ s/\/$//;
  252. $subcode = $r;
  253. } else {
  254. print "$nick: Unbalanced slashes. Usage: !cc s/regex/substitution/[gi] [and s/.../.../ [and ...]]\n";
  255. exit 0;
  256. }
  257. my $suffix;
  258. $suffix = $1 if $subcode =~ s/^([^ ]+)//;
  259. if(length $suffix and $suffix =~ m/[^gi]/) {
  260. print "$nick: Bad regex modifier '$suffix'. Only 'i' and 'g' are allowed.\n";
  261. exit 0;
  262. }
  263. if(defined $prevchange) {
  264. $code = $prevchange;
  265. } else {
  266. print "$nick: No recent code to change.\n";
  267. exit 0;
  268. }
  269. my $ret = eval {
  270. my $ret;
  271. my $a;
  272. my $b;
  273. my $c;
  274. my $d;
  275. my $e;
  276. my $f;
  277. my $g;
  278. my $h;
  279. my $i;
  280. my $before;
  281. my $after;
  282. if(not length $suffix) {
  283. $ret = $code =~ s|$regex|$to|;
  284. $a = $1;
  285. $b = $2;
  286. $c = $3;
  287. $d = $4;
  288. $e = $5;
  289. $f = $6;
  290. $g = $7;
  291. $h = $8;
  292. $i = $9;
  293. $before = $`;
  294. $after = $';
  295. } elsif($suffix =~ /^i$/) {
  296. $ret = $code =~ s|$regex|$to|i;
  297. $a = $1;
  298. $b = $2;
  299. $c = $3;
  300. $d = $4;
  301. $e = $5;
  302. $f = $6;
  303. $g = $7;
  304. $h = $8;
  305. $i = $9;
  306. $before = $`;
  307. $after = $';
  308. } elsif($suffix =~ /^g$/) {
  309. $ret = $code =~ s|$regex|$to|g;
  310. $a = $1;
  311. $b = $2;
  312. $c = $3;
  313. $d = $4;
  314. $e = $5;
  315. $f = $6;
  316. $g = $7;
  317. $h = $8;
  318. $i = $9;
  319. $before = $`;
  320. $after = $';
  321. } elsif($suffix =~ /^ig$/ or $suffix =~ /^gi$/) {
  322. $ret = $code =~ s|$regex|$to|gi;
  323. $a = $1;
  324. $b = $2;
  325. $c = $3;
  326. $d = $4;
  327. $e = $5;
  328. $f = $6;
  329. $g = $7;
  330. $h = $8;
  331. $i = $9;
  332. $before = $`;
  333. $after = $';
  334. }
  335. if($ret) {
  336. $code =~ s/\$1/$a/g;
  337. $code =~ s/\$2/$b/g;
  338. $code =~ s/\$3/$c/g;
  339. $code =~ s/\$4/$d/g;
  340. $code =~ s/\$5/$e/g;
  341. $code =~ s/\$6/$f/g;
  342. $code =~ s/\$7/$g/g;
  343. $code =~ s/\$8/$h/g;
  344. $code =~ s/\$9/$i/g;
  345. $code =~ s/\$`/$before/g;
  346. $code =~ s/\$'/$after/g;
  347. }
  348. return $ret;
  349. };
  350. if($@) {
  351. print "$nick: $@\n";
  352. exit 0;
  353. }
  354. if($ret) {
  355. $got_changes = 1;
  356. }
  357. $prevchange = $code;
  358. }
  359. if($got_sub and not $got_changes) {
  360. print "$nick: No substitutions made.\n";
  361. exit 0;
  362. } elsif($got_sub and $got_changes) {
  363. next;
  364. }
  365. last;
  366. }
  367. if($#replacements > -1) {
  368. @replacements = sort { $a->{'from'} cmp $b->{'from'} or $a->{'modifier'} <=> $b->{'modifier'} } @replacements;
  369. my ($previous_from, $previous_modifier);
  370. foreach my $replacement (@replacements) {
  371. my $from = $replacement->{'from'};
  372. my $to = $replacement->{'to'};
  373. my $modifier = $replacement->{'modifier'};
  374. if(defined $previous_from) {
  375. if($previous_from eq $from and $previous_modifier =~ /^\d+$/) {
  376. $modifier -= $modifier - $previous_modifier;
  377. }
  378. }
  379. if(defined $prevchange) {
  380. $code = $prevchange;
  381. } else {
  382. print "$nick: No recent code to change.\n";
  383. exit 0;
  384. }
  385. my $ret = eval {
  386. my $got_change;
  387. my ($first_char, $last_char, $first_bound, $last_bound);
  388. $first_char = $1 if $from =~ m/^(.)/;
  389. $last_char = $1 if $from =~ m/(.)$/;
  390. if($first_char =~ /\W/) {
  391. $first_bound = '.';
  392. } else {
  393. $first_bound = '\b';
  394. }
  395. if($last_char =~ /\W/) {
  396. $last_bound = '\B';
  397. } else {
  398. $last_bound = '\b';
  399. }
  400. if($modifier eq 'all') {
  401. while($code =~ s/($first_bound)$from($last_bound)/$1$to$2/) {
  402. $got_change = 1;
  403. }
  404. } elsif($modifier eq 'last') {
  405. if($code =~ s/(.*)($first_bound)$from($last_bound)/$1$2$to$3/) {
  406. $got_change = 1;
  407. }
  408. } else {
  409. my $count = 0;
  410. my $unescaped = $from;
  411. $unescaped =~ s/\\//g;
  412. if($code =~ s/($first_bound)$from($last_bound)/if(++$count == $modifier) { "$1$to$2"; } else { "$1$unescaped$2"; }/gex) {
  413. $got_change = 1;
  414. }
  415. }
  416. return $got_change;
  417. };
  418. if($@) {
  419. print "$nick: $@\n";
  420. exit 0;
  421. }
  422. if($ret) {
  423. $got_sub = 1;
  424. $got_changes = 1;
  425. }
  426. $prevchange = $code;
  427. $previous_from = $from;
  428. $previous_modifier = $modifier;
  429. }
  430. if($got_sub and not $got_changes) {
  431. print "$nick: No replacements made.\n";
  432. exit 0;
  433. }
  434. }
  435. open FILE, "> ideone_last_code.txt";
  436. unless ($got_undo and not $got_sub) {
  437. unshift @last_code, $code;
  438. }
  439. my $i = 0;
  440. foreach my $line (@last_code) {
  441. last if(++$i > $MAX_UNDO_HISTORY);
  442. print FILE "$line\n";
  443. }
  444. close FILE;
  445. if($got_undo and not $got_sub) {
  446. print "$nick: $code\n";
  447. exit 0;
  448. }
  449. }
  450. unless($got_run) {
  451. open FILE, ">> ideone_log.txt";
  452. print FILE "$nick: $code\n";
  453. }
  454. my $lang = "C99";
  455. $lang = $1 if $code =~ s/-lang=([^\b\s]+)//i;
  456. $lang = "C" if $code =~ s/-nowarn[ings]*//i;
  457. my $show_link = 0;
  458. $show_link = 1 if $code =~ s/-showurl//i;
  459. my $found = 0;
  460. my @langs;
  461. foreach my $l (sort { uc $a cmp uc $b } keys %languages) {
  462. push @langs, sprintf(" %-30s => %s", $l, $languages{$l}{'name'});
  463. if(uc $lang eq uc $l) {
  464. $lang = $l;
  465. $found = 1;
  466. }
  467. }
  468. if(not $found) {
  469. print "$nick: Invalid language '$lang'. Supported languages are:\n", (join ",\n", @langs), "\n";
  470. exit 0;
  471. }
  472. my $input = "";
  473. $input = $1 if $code =~ s/-input=(.*)$//i;
  474. $code =~ s/#include <([^>]+)>/\n#include <$1>\n/g;
  475. $code =~ s/#([^ ]+) (.*?)\\n/\n#$1 $2\n/g;
  476. $code =~ s/#([\w\d_]+)\\n/\n#$1\n/g;
  477. my $precode = $preludes{$languages{$lang}{'id'}} . $code;
  478. $code = '';
  479. if($languages{$lang}{'id'} == 1 or $languages{$lang}{'id'} == 11 or $languages{$lang}{'id'} == 34) {
  480. my $has_main = 0;
  481. my $prelude = '';
  482. $prelude = "$1$2" if $precode =~ s/^\s*(#.*)(#.*?[>\n])//s;
  483. while($precode =~ s/([ a-zA-Z0-9_*\[\]]+)\s+([a-zA-Z0-9_*]+)\s*\((.*?)\)\s*({.*)//) {
  484. my ($ret, $ident, $params, $potential_body) = ($1, $2, $3, $4);
  485. my @extract = extract_codeblock($potential_body, '{}');
  486. my $body;
  487. if(not defined $extract[0]) {
  488. $output .= "error: unmatched brackets for function '$ident';\n";
  489. $body = $extract[1];
  490. } else {
  491. $body = $extract[0];
  492. $precode .= $extract[1];
  493. }
  494. $code .= "$ret $ident($params) $body\n\n";
  495. $has_main = 1 if $ident eq 'main';
  496. }
  497. $precode =~ s/^\s+//;
  498. $precode =~ s/\s+$//;
  499. if(not $has_main) {
  500. $code = "$prelude\n\n$code\n\nint main(int argc, char **argv) { $precode\n;\n return 0;}\n";
  501. $nooutput = "Success [no output].";
  502. } else {
  503. $code = "$prelude\n\n$precode\n\n$code\n";
  504. $nooutput = "No output.";
  505. }
  506. } else {
  507. $code = $precode;
  508. }
  509. if($languages{$lang}{'id'} == 1 or $languages{$lang}{'id'} == 11 or $languages{$lang}{'id'} == 35
  510. or $languages{$lang}{'id'} == 27 or $languages{$lang}{'id'} == 10 or $languages{$lang}{'id'} == 34) {
  511. $code = pretty($code)
  512. }
  513. $code =~ s/\\n/\n/g if $languages{$lang}{'id'} == 13 or $languages{$lang}{'id'} == 101 or $languages{$lang}{'id'} == 45;
  514. $code =~ s/;/\n/g if $languages{$lang}{'id'} == 13 or $languages{$lang}{'id'} == 45;
  515. $code =~ s/\|n/\n/g;
  516. $code =~ s/^\s+//;
  517. $code =~ s/\s+$//;
  518. $result = get_result($soap->createSubmission($user, $pass, $code, $languages{$lang}{'id'}, $input, 1, 1));
  519. my $url = $result->{link};
  520. # wait for compilation/execution to complete
  521. while(1) {
  522. $result = get_result($soap->getSubmissionStatus($user, $pass, $url));
  523. last if $result->{status} == 0;
  524. sleep 1;
  525. }
  526. $result = get_result($soap->getSubmissionDetails($user, $pass, $url, 0, 0, 1, 1, 1));
  527. my $COMPILER_ERROR = 11;
  528. my $RUNTIME_ERROR = 12;
  529. my $TIMELIMIT = 13;
  530. my $SUCCESSFUL = 15;
  531. my $MEMORYLIMIT = 17;
  532. my $ILLEGAL_SYSCALL = 19;
  533. my $INTERNAL_ERROR = 20;
  534. # signals extracted from ideone.com
  535. my @signame;
  536. $signame[0] = 'SIGZERO';
  537. $signame[1] = 'SIGHUP';
  538. $signame[2] = 'SIGINT';
  539. $signame[3] = 'SIGQUIT';
  540. $signame[4] = 'SIGILL';
  541. $signame[5] = 'SIGTRAP';
  542. $signame[6] = 'SIGABRT';
  543. $signame[7] = 'SIGBUS';
  544. $signame[8] = 'SIGFPE';
  545. $signame[9] = 'SIGKILL';
  546. $signame[10] = 'SIGUSR1';
  547. $signame[11] = 'SIGSEGV';
  548. $signame[12] = 'SIGUSR2';
  549. $signame[13] = 'SIGPIPE';
  550. $signame[14] = 'SIGALRM';
  551. $signame[15] = 'SIGTERM';
  552. $signame[16] = 'SIGSTKFLT';
  553. $signame[17] = 'SIGCHLD';
  554. $signame[18] = 'SIGCONT';
  555. $signame[19] = 'SIGSTOP';
  556. $signame[20] = 'SIGTSTP';
  557. $signame[21] = 'SIGTTIN';
  558. $signame[22] = 'SIGTTOU';
  559. $signame[23] = 'SIGURG';
  560. $signame[24] = 'SIGXCPU';
  561. $signame[25] = 'SIGXFSZ';
  562. $signame[26] = 'SIGVTALRM';
  563. $signame[27] = 'SIGPROF';
  564. $signame[28] = 'SIGWINCH';
  565. $signame[29] = 'SIGIO';
  566. $signame[30] = 'SIGPWR';
  567. $signame[31] = 'SIGSYS';
  568. $signame[32] = 'SIGNUM32';
  569. $signame[33] = 'SIGNUM33';
  570. $signame[34] = 'SIGRTMIN';
  571. $signame[35] = 'SIGNUM35';
  572. $signame[36] = 'SIGNUM36';
  573. $signame[37] = 'SIGNUM37';
  574. $signame[38] = 'SIGNUM38';
  575. $signame[39] = 'SIGNUM39';
  576. $signame[40] = 'SIGNUM40';
  577. $signame[41] = 'SIGNUM41';
  578. $signame[42] = 'SIGNUM42';
  579. $signame[43] = 'SIGNUM43';
  580. $signame[44] = 'SIGNUM44';
  581. $signame[45] = 'SIGNUM45';
  582. $signame[46] = 'SIGNUM46';
  583. $signame[47] = 'SIGNUM47';
  584. $signame[48] = 'SIGNUM48';
  585. $signame[49] = 'SIGNUM49';
  586. $signame[50] = 'SIGNUM50';
  587. $signame[51] = 'SIGNUM51';
  588. $signame[52] = 'SIGNUM52';
  589. $signame[53] = 'SIGNUM53';
  590. $signame[54] = 'SIGNUM54';
  591. $signame[55] = 'SIGNUM55';
  592. $signame[56] = 'SIGNUM56';
  593. $signame[57] = 'SIGNUM57';
  594. $signame[58] = 'SIGNUM58';
  595. $signame[59] = 'SIGNUM59';
  596. $signame[60] = 'SIGNUM60';
  597. $signame[61] = 'SIGNUM61';
  598. $signame[62] = 'SIGNUM62';
  599. $signame[63] = 'SIGNUM63';
  600. $signame[64] = 'SIGRTMAX';
  601. $signame[65] = 'SIGIOT';
  602. $signame[66] = 'SIGCLD';
  603. $signame[67] = 'SIGPOLL';
  604. $signame[68] = 'SIGUNUSED';
  605. if($result->{result} != $SUCCESSFUL or $languages{$lang}{'id'} == 13) {
  606. $output .= $result->{cmpinfo};
  607. $output =~ s/[\n\r]/ /g;
  608. }
  609. if($result->{result} == $RUNTIME_ERROR) {
  610. $output .= "\n[Runtime error]";
  611. if($result->{signal}) {
  612. $output .= "\n[Signal: $signame[$result->{signal}] ($result->{signal})]";
  613. }
  614. } else {
  615. if($result->{signal}) {
  616. $output .= "\n[Exit code: $result->{signal}]";
  617. }
  618. }
  619. if($result->{result} == $TIMELIMIT) {
  620. $output .= "\n[Time limit exceeded]";
  621. }
  622. if($result->{result} == $MEMORYLIMIT) {
  623. $output .= "\n[Out of memory]";
  624. }
  625. if($result->{result} == $ILLEGAL_SYSCALL) {
  626. $output .= "\n[Disallowed system call]";
  627. }
  628. if($result->{result} == $INTERNAL_ERROR) {
  629. $output .= "\n[Internal error]";
  630. }
  631. $output .= "\n" . $result->{stderr};
  632. $output .= "\n" . $result->{output};
  633. $output = decode_entities($output);
  634. $output =~ s/cc1: warnings being treated as errors//;
  635. $output =~ s/ Line \d+ ://g;
  636. $output =~ s/ \(first use in this function\)//g;
  637. $output =~ s/error: \(Each undeclared identifier is reported only once.*?\)//msg;
  638. $output =~ s/prog\.c:[:\s\d]*//g;
  639. $output =~ s/ld: warning: cannot find entry symbol _start; defaulting to [^ ]+//;
  640. $output =~ s/error: (.*?) error/error: $1; error/msg;
  641. my $left_quote = chr(226) . chr(128) . chr(152);
  642. my $right_quote = chr(226) . chr(128) . chr(153);
  643. $output =~ s/$left_quote/'/g;
  644. $output =~ s/$right_quote/'/g;
  645. $output = $nooutput if $output =~ m/^\s+$/;
  646. unless($got_run) {
  647. print FILE localtime() . "\n";
  648. print FILE "$nick: [ http://ideone.com/$url ] $output\n\n";
  649. close FILE;
  650. }
  651. if($show_link) {
  652. print "$nick: [ http://ideone.com/$url ] $output\n";
  653. } else {
  654. print "$nick: $output\n";
  655. }
  656. # ---------------------------------------------
  657. sub get_result {
  658. my $result = shift @_;
  659. use Data::Dumper;
  660. if($result->fault) {
  661. print join ', ', $result->faultcode, $result->faultstring, $result->faultdetail;
  662. exit 0;
  663. } else {
  664. if($result->result->{error} ne "OK") {
  665. print "error\n";
  666. print Dumper($result->result->{error});
  667. exit 0;
  668. } else {
  669. return $result->result;
  670. }
  671. }
  672. }
  673. sub pretty {
  674. my $code = join '', @_;
  675. my $result;
  676. my $pid = open2(\*IN, \*OUT, 'astyle -xUpf');
  677. print OUT "$code\n";
  678. close OUT;
  679. while(my $line = <IN>) {
  680. $result .= $line;
  681. }
  682. close IN;
  683. waitpid($pid, 0);
  684. return $result;
  685. }