#!/usr/bin/perl use strict; use IPC::Open2; use IO::Socket::INET; use Time::HiRes; use Getopt::Std; use Socket qw(IPPROTO_TCP TCP_NODELAY); my ($tex,$texfile,$debuglevel) = ("tex","main.tex",0); my %args; getopts('d:lf:',\%args); $debuglevel = $args{'d'} if defined $args{'d'}; $tex = "pdflatex" if defined $args{'l'}; $texfile = $args{'f'} if defined $args{'f'}; my $oldh = select(STDERR); $| = 1; select($oldh); my $pid = open2 *TEXOUT, *TEXIN, "$tex $texfile" or die "cannot connect to TeX"; open TEXLOG, ">texlog"; my $host = shift or 'localhost'; my $port = shift or '17676'; my $socket = IO::Socket::INET->new(Proto => "tcp", PeerAddr => $host, PeerPort => $port, Blocking => 0) or die "cannot connect to TCP server $host:$port"; $socket->setsockopt(IPPROTO_TCP,TCP_NODELAY,1); my @lines = ('')x30; my $lasttics = 0; my $clockoffset=0; my ($start,$startu)=Time::HiRes::gettimeofday(); my $initline = ''; my $noterr = 0; # TeX doesn't just stop for errors... while () { print if $debuglevel>6; if (/\! OK/) { $noterr++; } if (/WANT/) { print STDERR "." if $debuglevel>5; my $data = <$socket>; my ($time,$timeu)=Time::HiRes::gettimeofday(); $time -= $start; $timeu -= $startu; my $tics = 1000*$time+int($timeu/1000)-$clockoffset; if ($data) { $initline = $data if $data=~/I/; if ($data=~/T 0/) { $clockoffset += $tics; $tics = 0 } print STDERR "Transmitted packet: $data\n" if $debuglevel>3; print TEXIN "t $tics ; $data\n"; print TEXLOG "t $tics ; $data\n"; } else { unless ($socket->connected) { print TEXIN "\\done\n"; print STDERR "Server disconnected\n" if $debuglevel>-1; close TEXIN; close TEXOUT; } else { if ($tics-$lasttics<10) { Time::HiRes::usleep(1000*(10+$lasttics-$tics)); ($time,$timeu)=Time::HiRes::gettimeofday(); $time -= $start; $timeu -= $startu; $tics = 1000*$time+int($timeu/1000)-$clockoffset; } print TEXIN "t $tics ;\n"; print TEXLOG "t $tics ;\n"; } } $lasttics=$tics; } elsif (/HERE: (.*)$/) { print STDERR "Got message: $1\n" if $debuglevel>1; print $socket $1; } elsif (/DEBUG\((.*)\): (.*)$/) { print STDERR "$2\n" if $1<=$debuglevel; } elsif (/DONE/) { while () { print STDERR $_ } close TEXIN; close TEXOUT; close $socket; } else { if (/\S+/) { shift @lines; push @lines,$_; } } if (/^l\./) { if ($noterr) { print TEXIN "\n"; $noterr--; } else { print STDERR "TeX Error: $_\n" if $debuglevel>=0; $"=''; print "@lines"; print TEXIN "x\nx\nx\nx\nx\n"; for (my $i=0;$i<20;++$i) { print } close TEXIN; close TEXOUT; close TEXLOG; kill $pid; system "cp main.log error.log"; system "cp texlog texlog.1"; print STDERR "log file copied\n"; $pid = open2 *TEXOUT, *TEXIN, "$tex $texfile" or die "cannot connect to TeX"; my $data = ''; while ($data!~/E/) { last unless $socket->connected; open TEXLOG, ">texlog"; $data = <$socket> } while () { # wait till we're good to go print TEXIN "$initline\n" and last if /WANT/; } } } } print STDERR "Remaining data:\n" if $debuglevel>-1; while (<$socket>) { print STDERR "$_\n" if $debuglevel >-1 } close $socket; close TEXLOG;