#!/usr/bin/perl # # $Id: pr2troff,v 1.5 2000/06/30 00:29:14 vogelke Exp $ # # NAME: # pr2troff # # SYNOPSIS: # pr2troff [-v] file # # DESCRIPTION: # "pr2troff" reads a problem report file and writes the # troff equivalent to stdout. Use "groff -me -Tps" to format, # or "ptroff -me -t"; the regular troff program has some trouble # with this. # # OPTIONS: # "-v" prints the current version and exits. # # NOTES: # The output format uses pages based on the month and the year, to # make updates easier to print. If you want to print a given # section starting at (say) November 1997, generate the output # normally and then edit it. Keep the top macros: # # .de Vb # .ft CW # .nf # .na # .in 0 # .if \\$1 .ne \\$1 # .. # .de Ve # .in 2 # .ft R # .fi # .ad # .. # # Add a page break: # # nothing here # .bp # # Delete everything up to the starting month: # # .in 0 # .sp # .ad # .fi # .ne 1 # .br # .ie e \{\ # . eh '247: Software procurement' 'Nov-1997-%' # . oh '247: Software procurement' 'Nov-1997-%' # . bp 1 \} # .el \{\ # . eh '''' # . oh '''' # . bp # . sp 10 # This page intentionally left blank. # . eh '247: Software procurement' 'Nov-1997-%' # . oh '247: Software procurement' 'Nov-1997-%' # . bp 1 \} # \s+2\fBMon, 3 Nov 1997 16:28:53 -0500 # # Then print as usual. Someday I may add this as a command-line # option. # # It's actually not too hard to edit the generated PostScript. # # AUTHOR: # Karl E. Vogel # Sumaria Systems, Inc. eval 'exec perl -S $0 ${1+"$@"}' # If the shell can't handle "#!", if 0; # fire up perl directly. require "getopts.pl"; # command line args. $ENV{"PATH"} = "/bin:/usr/sbin:/usr/local/bin"; ($myname) = split (/\//, reverse ($0)); $myname = reverse ($myname); # script basename. # # Trap most common signals. Handle command line arguments (if any). # $SIG{'HUP'} = 'sigcatcher'; $SIG{'INT'} = 'sigcatcher'; $SIG{'QUIT'} = 'sigcatcher'; $SIG{'TERM'} = 'sigcatcher'; &usage unless &Getopts ('v'); $version = &version; do {print "$version\n"; exit (0);} if $opt_v; # # Read a problem report. # Need to read the header separately because we need a # date to form the top section number. # $_ = shift (@ARGV); die "I need a problem report to read.\n" if length ($_) == 0; if (/^[0-9]+$/) # gave just the number, so prepend directory. { $n = sprintf ("%4.4d", $_); $dir = substr ($n, 0, 1); $base = substr ($n, 1); $file = "/var/prob/spool/$dir/$base"; } else { $file = $_; } open (IN, "$file") || die "$file: can't open: $!\n"; $k = 0; while () { chop; last if /^\s*$/; # blank line, end of header $header[$k] = $_; $k++; if (/^Ticket-Id:/) { ($junk, $ticket) = split; } elsif (/^Subject:/) # get current subject, use as banner { # across page top. Escape single quotes. s/^Subject:\t*//g; s/'/\\'/g; $banner = $_; } elsif (/^Date:/) # use date to indicate a printed section. { s/^Date:\t*//g; @a = split; $section = $a[2] . "-" . $a[3]; } } # # Final pass. Write introduction, macros. The Vb/Ve macro pair is # used to write things that must appear exactly as printed. In this # example, the 5 lines shown would appear in Courier type, and they will # NOT be broken across a page boundary. # # .Vb 5 # \& This is line 1 # \& This is line 2 # \& This is line 3 # \& This is line 4 # \& This is line 5 # .Ve # # Leaving off the argument will allow page breaks at any point. # print <<"EOF"; .\\" Generated from $file .\\" by $version .\\" Use "groff -me -Tps" to format. .de Vb .ft CW .nf .na .in 0 .if \\\\\$1 .ne \\\\\$1 .. .de Ve .in 2 .ft R .fi .ad .. .eh '$ticket: $banner' '$section-%' .oh '$ticket: $banner' '$section-%' .ta 1i EOF # # Print the header. # foreach (@header) { @s = split; $field = shift (@s); print "\\fB$field\\fR\t@s\n.br\n"; } &border; # # Print the body. # $preformat = 0; $dotwarn = "WARNING: possible unplanned dot command at line"; $k = 0; while () { chop; $k++; $_ = &tab_expand ($_); s/\\/\\\\/g; # Make sure backslashes print properly. if (/^BEGINNING OF LOG FOR/) # section header { s/=*//g; print ".in 0\n\\s+3\\fB$_\\fR\\s-3\n"; } elsif (/^[A-Z]/) # begin dated entry { print ".in 0\n.sp\n.ad\n.fi\n.ne 1\n"; # Increment section and page if month changes. # # If we're on an even page and we're printing this # double-sided, we'll have a new month starting on # the back of a page; this makes replacement of a # section difficult, so we add an additional page break. @a = split; $newsect = $a[2] . "-" . $a[3]; if ($newsect ne $section) { $section = $newsect; print ".br\n"; print ".ie e \\{\\\n"; print ".\teh '$ticket: $banner' '$section-%'\n"; print ".\toh '$ticket: $banner' '$section-%'\n"; print ".\tbp 1 \\}\n"; print ".el \\{\\\n"; print ".\teh ''''\n"; print ".\toh ''''\n"; print ".\tbp\n"; print ".\tsp 10\n"; print "\tThis page intentionally left blank.\n"; print ".\teh '$ticket: $banner' '$section-%'\n"; print ".\toh '$ticket: $banner' '$section-%'\n"; print ".\tbp 1 \\}\n"; } print "\\s+2\\fB$_\\fR\\s-2\n"; print ".in 2\n"; } else # text, possibly preformatted { if (/----S$/) { print ".Vb\n"; $preformat = 1; } elsif (/----E$/) { print ".Ve\n"; $preformat = 0; } else { if ($preformat == 0) { s/^\s*//g; print "$_\n"; # watch for lines starting with dot! if (/^\./) { print STDERR "$dotwarn $k\n"; } } else { s/^ //; print "\\\& $_\n"; } } } } close (IN); print ".sp\n.in 0\n"; &border; print ".br\n\\fBEND\\fR\n"; &exit (0); #--------------------------------------------------------------------- # Print a short usage message from the comment header and exit. # sub usage { if (open (PROG, "$myname")) { while () { last if /^# NAME:/; } print STDERR " NAME:\n"; while () { last if /^\s*$/; last if /^# AUTHOR:/; s/^#//; print STDERR; } close (PROG); } else { print STDERR "No usage information available.\n" ; } &exit (1); } #--------------------------------------------------------------------- # Do something if we get a signal. # sub sigcatcher { local($sig) = @_; &exit (2, "caught signal SIG$sig -- shutting down.\n"); } #--------------------------------------------------------------------- # Print the current version and exit. # sub version { $_ = '$RCSfile: pr2troff,v $ $Revision: 1.5 $ ' . '$Date: 2000/06/30 00:29:14 $'; s/RCSfile: //; s/.Date: //; s/,v . .Revision: / v/; s/\$//g; return "$_"; } #--------------------------------------------------------------------- # Clean up. # sub exit { local($code, $msg) = @_; unlink ($tmp); warn "$myname: $msg\n" if $msg; exit ($code); } #--------------------------------------------------------------------- # Expand tabs in a string to 8 spaces. # # This seems to work best; if you want to shrink the size of a line with # lots of tabs, use "expand -5" to preserve most of the formatting. # # The leading two spaces are removed from preformatted lines to keep # line size down; see the bottom portion of the main program loop. sub tab_expand { local($_) = shift; 1 while s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e; return $_; } #--------------------------------------------------------------------- # Print long horizontal line. sub border { print "_____________________________________________"; print "_____________________________________________\n"; }