From dc2ba49207af71193f1390d84bba4e15aeea0ce0 Mon Sep 17 00:00:00 2001 From: Thomas Deutschmann Date: Thu, 19 Mar 2020 13:53:45 +0100 Subject: Import Ghostscript 9.52 Signed-off-by: Thomas Deutschmann --- toolbin/genfontmap.ps | 16 +- toolbin/halftone/thresh_remap/thresh_remap.c | 2 +- toolbin/headercompile.pl | 0 toolbin/localcluster/clusterpush.pl | 3 + toolbin/pdf_info.ps | 428 --------------------------- toolbin/squeeze2text.py | 85 ++++++ toolbin/vdb.pl | 280 +++++++++++++++--- 7 files changed, 341 insertions(+), 473 deletions(-) mode change 100644 => 100755 toolbin/headercompile.pl delete mode 100644 toolbin/pdf_info.ps create mode 100755 toolbin/squeeze2text.py (limited to 'toolbin') diff --git a/toolbin/genfontmap.ps b/toolbin/genfontmap.ps index 86b26ea5..565dcc74 100644 --- a/toolbin/genfontmap.ps +++ b/toolbin/genfontmap.ps @@ -16,10 +16,15 @@ % Create a Fontmap format file after scanning the FONTPATH directories % +% From Ghostscript version 9.50 onwards the default operation is to run with +% SAFER defined; this disables a number of PostScript operators, specifically +% in this case the .sort operator, which is used by this program. In order +% to use this program you must run with -dNOSAFER. +% % Example usage: -% windows: gswin32c -q -sFONTPATH=c:/windows/fonts genfontmap.ps > myFontmap +% windows: gswin32c -dNOSAFER -q -sFONTPATH=c:/windows/fonts genfontmap.ps > myFontmap % -% unix: gs -q -sFONTPATH=/usr/local/fonts genfontmap.ps > myFontmap +% unix: gs -dNOSAFER -q -sFONTPATH=/usr/local/fonts genfontmap.ps > myFontmap % % The myFontmap file created by the above can be renamed to Fontmap and % placed in the LIBPATH directory. @@ -33,6 +38,13 @@ FONTPATH length 0 eq { flush quit } if +% Since version 9.50, ensure we are running in NOSAFER so that .sort is available +/NOSAFER where {/NOSAFER get not}{true} ifelse +{ + (\n You must use the '-dNOSAFER' option in order to execute this program.\n\n) =error + flush quit +} if + QUIET not { (\n You must use the '-q' option in order to generate a clean Fontmap.\n\n) =error flush quit diff --git a/toolbin/halftone/thresh_remap/thresh_remap.c b/toolbin/halftone/thresh_remap/thresh_remap.c index 87b6b8b2..59ad8b65 100644 --- a/toolbin/halftone/thresh_remap/thresh_remap.c +++ b/toolbin/halftone/thresh_remap/thresh_remap.c @@ -192,7 +192,7 @@ main( int argc, char *argv[]) { fprintf(ofile,"%%%%EOF\n"); } else { /* Just dump the binary data (suitable for Scanvec */ - fprintf(ofile, "%c%c", width/256, width>>256); + fprintf(ofile, "%c%c", width/256, width % 256); for (i=0; i printXML - - % print non-blank lines without trailing spaces - dup dup length 1 sub -1 0 { - 1 index 1 index get 32 eq { - 0 exch getinterval exch - } { - exch = exit % non-blank on this line - } - ifelse - } for - pop pop % clean up -} bind def - -/dump-pdf-info { % (fname) -> - - () = ( ) print print ( has ) print - PDFPageCount dup =print 10 mod 1 eq { ( page.\n) } { ( pages\n) } ifelse = flush - - Trailer /Root oget /AcroForm knownoget { - /XFA knownoget { - (File uses XFA forms.\n\n) print - pop - } if - } if - - /DumpXML where { - pop - Trailer /Root oget /Metadata knownoget { - //false resolvestream - { dup 256 string readline exch printXML not { exit } if } loop - pop % done with the stream - (_____________________________________________________________) = - flush - } if - } if - - % Print out the "Info" dictionary if present - Trailer /Info knownoget { - dup /Title knownoget { (Title: ) print = flush } if - dup /Author knownoget { (Author: ) print = flush } if - dup /Subject knownoget { (Subject: ) print = flush } if - dup /Keywords knownoget { (Keywords: ) print = flush } if - dup /Creator knownoget { (Creator: ) print = flush } if - dup /Producer knownoget { (Producer: ) print = flush } if - dup /CreationDate knownoget { (CreationDate: ) print = flush } if - dup /ModDate knownoget { (ModDate: ) print = flush } if - dup /Trapped knownoget { (Trapped: ) print = flush } if - pop - } if - -} bind def - -% dump-media-sizes - -/dump-media-sizes { - DumpMediaSizes { - () = - % Print out the Page Size info for each page. - (Page ) print =print - dup /UserUnit pget { - ( UserUnit: ) print =print - } if - dup /MediaBox pget { - ( MediaBox: ) print oforce_array ==only - } if - dup /CropBox pget { - ( CropBox: ) print oforce_array ==only - } if - dup /BleedBox pget { - ( BleedBox: ) print oforce_array ==only - } if - dup /TrimBox pget { - ( TrimBox: ) print oforce_array ==only - } if - dup /ArtBox pget { - ( ArtBox: ) print oforce_array ==only - } if - dup /Rotate pget { - ( Rotate = ) print =print - } if - dup /Annots pget { - pop - ( Page contains Annotations) print - } if - pageusestransparency { - ( Page uses transparency features) print - } if - () = flush - } - { - pop pop - } ifelse -} bind def - -% List of standard font names for use when we are showing the FontsNeeded -/StdFontNames [ - /Times-Roman /Helvetica /Courier /Symbol - /Times-Bold /Helvetica-Bold /Courier-Bold /ZapfDingbats - /Times-Italic /Helvetica-Oblique /Courier-Oblique - /Times-BoldItalic /Helvetica-BoldOblique /Courier-BoldOblique -] def - -/res-type-dict 10 dict begin - /Font { - { - exch pop oforce_no_circular - dup //null ne { - dup /DescendantFonts knownoget { - exch pop 0 get oforce_no_circular - %% Check to see if a potentail circular reference was detected. This could be a - %% false positive caused by other fonts using the same DescendantFont(s), but if - %% so then we've already cehcked them anyway. - dup //null eq { pop << >>} if - } if - dup /FontDescriptor knownoget { - dup /FontFile known 1 index /FontFile2 known or exch /FontFile3 known or - /ShowEmbeddedFonts where { pop pop //false } if { - pop % skip embedded fonts - } { - /BaseFont knownoget { % not embedded - 2 index exch //null put - } if - } ifelse - } { - /BaseFont knownoget { % no FontDescriptor, not embedded - 2 index exch //null put - } if - } ifelse - } { - pop - } ifelse - } forall % traverse the dictionary - } bind def - - /XObject { - { - exch pop oforce_no_circular - dup //null ne { - dup /Subtype knownoget { - /Form eq { - /Resources knownoget { - get-fonts-from-res - } if - } { - pop - } ifelse - } { - pop - } ifelse - } { - pop - } ifelse - } forall - } bind def - - /Pattern { - { - exch pop oforce_no_circular - dup //null ne { - /Resources knownoget { - get-fonts-from-res - } if - } { - pop - } ifelse - } forall - } bind def -currentdict end readonly def - -% <> get-fonts-from-res - -/get-fonts-from-res { - oforce_no_circular - dup //null ne { - { - oforce_no_circular - dup //null ne { - //res-type-dict 3 -1 roll - .knownget { - exec - } { - pop - } ifelse - } { - pop pop - } ifelse - } forall - } { - pop - } ifelse -} bind def - -currentdict /res-type-dict undef - -/getPDFfonts { % getPDFfonts - - /ProcessedResources 10 dict def - dup /Resources pget { get-fonts-from-res } if - /Annots knownoget { - { oforce_no_circular - dup //null ne { - /AP knownoget { - { exch pop oforce_no_circular - dup //null ne { - dup /Resources knownoget { - get-fonts-from-res - } if - { exch pop oforce_no_circular - dup type /dicttype eq { - /Resources knownoget { - get-fonts-from-res - } if - } { - pop - } ifelse - } forall - } { - pop - } ifelse - } forall - } if - } { - pop - } ifelse - } forall - } if - pop - currentdict /ProcessedResources undef -} bind def - -/dump-fonts-used { % dump-fonts-used - - % If DumpFontsUsed is not true, then remove the 'standard' fonts from the list - systemdict /DumpFontsUsed known not { - StdFontNames { - 1 index 1 index known { 1 index 1 index undef } if - pop - } forall - } if - - % Now dump the FontsUsed dict into an array so we can sort it. - [ 1 index { pop } forall ] - { 100 string cvs exch 100 string cvs exch lt } .sort - - systemdict /DumpFontsUsed known - { - (\nFont or CIDFont resources used:) = - { = } forall - } { - DumpFontsNeeded { - dup length 0 gt { - (\nFonts Needed that are not embedded \(system fonts required\):) = - { ( ) print = } forall - } { - pop - (\nNo system fonts are needed.) = - } ifelse - } { - pop - } ifelse - } ifelse - pop -} bind def - -% Copy selected subfiles to temporary files and return the file names -% as a PostScript names to protect them from restore. -% Currently, all PDF files in the Portfolio are extracted and returned. -% -% - pdf_collection_files [ /temp_file_name ... /temp_file_name -/pdf_collection_files { - mark - Trailer /Root oget - dup /Collection oknown { - /Names knownoget { - /EmbeddedFiles knownoget { - pdf_collection_names - } if - } if - } { - pop - } ifelse -} bind def - -% Output all the info about the file -/dump { % (title) -> - - /PDFPageCount pdfpagecount def - dump-pdf-info - % dict will be populated with fonts through a call to 'getPDFfonts' - % per page, then the contents dumped out in 'dump-fonts-used' - 1000 dict - - 1 1 PDFPageCount - { - dup pdfgetpage dup 3 -1 roll - dump-media-sizes - 1 index exch getPDFfonts - } for - - dump-fonts-used - -} bind def - -% Choose between collection vs plain file. -% Enumerate collections and apply the dump procedure. -/enum-pdfs { % - -> - - File (r) file runpdfbegin - pdf_collection_files - dup mark eq { - pop - File dump - runpdfend - } { - runpdfend - ] 0 1 2 index length 1 sub { - 2 copy get exch % [file ... ] file i - 1 add (0123456789) cvs % [file ... ] file (i+1) - File exch ( part ) exch concatstrings concatstrings - exch % [file ... ] (fname part i+1) file - dup type /filetype eq { - runpdfbegin - dump - runpdfend - closefile - } { - 1024 string cvs % .namestring is deprecated -% .namestring - dup (r) file - runpdfbegin - exch dump - runpdfend - deletefile - } ifelse - } for - pop - } ifelse -} bind def - -enum-pdfs -end -quit diff --git a/toolbin/squeeze2text.py b/toolbin/squeeze2text.py new file mode 100755 index 00000000..0f533d20 --- /dev/null +++ b/toolbin/squeeze2text.py @@ -0,0 +1,85 @@ +#!/usr/bin/python3 + +''' +Reads memento squeeze output from stdin, and writes brief info to stdout or +file. + +E.g.: + MEMENTO_SQUEEZEAT=1 ./membin/gpdl -sDEVICE=bit -o /dev/null examples/tiger.eps 2>&1 | toolbin/squeeze2text.py -o squeeze.txt + +Args: + + -a + Append output to . Write log to stdout. + -o + Write output to . Write log to stdout. + -p + Write progress information to log, every blocks. + +If -o is not specified, we write output to stdout, and log to stderr. + +If -p is not specified, default is -p 1. + +''' + +import io +import re +import sys + +if __name__ == '__main__': + + verbose = False + progress_n = 1 + num_segv = 0 + num_leak = 0 + out = sys.stdout + log = sys.stderr + + args = iter( sys.argv[1:]) + while 1: + try: + arg = next(args) + except StopIteration: + break + if arg == '-p': + progress_n = int( next(args)) + elif arg == '-a': + filename = next(args) + out = open( filename, 'a') + log = sys.stdout + elif arg == '-o': + filename = next(args) + out = open( filename, 'w') + log = sys.stdout + else: + raise Exception( 'unrecognised arg: %r' % arg) + + # Use latin_1 encoding to ensure we can read all 8-bit bytes from stdin as + # characters. + f = io.TextIOWrapper( sys.stdin.buffer, encoding='latin_1') + progress_n_next = 0 + + def print_progress(): + print( 'memento_n=%s. num_segv=%s num_leak=%s' % ( + memento_n, + num_segv, + num_leak + ), + file=log, + ) + + for line in f: + m = re.match( '^Memory squeezing @ ([0-9]+)$', line) + if m: + memento_n = int( m.group(1)) + if memento_n >= progress_n_next: + print_progress() + progress_n_next = int(memento_n / progress_n + 1) * progress_n + log.flush() # Otherwise buffered and we see no output for ages. + elif line.startswith( 'SEGV at:'): + num_segv += 1 + print( 'memento_n=%s: segv' % memento_n, file=out) + elif line.startswith( 'Allocated blocks'): + num_leak += 1 + print( 'memento_n=%s: leak' % memento_n, file=out) + print_progress() diff --git a/toolbin/vdb.pl b/toolbin/vdb.pl index 8555fc1c..3833f6fd 100644 --- a/toolbin/vdb.pl +++ b/toolbin/vdb.pl @@ -3,12 +3,64 @@ # Perl script to ease the use of gdb with valgrind. # # Invoke as: vdb.pl +# +# This also adds some commands to the usual gdb/valgrind +# stuff. +# +# xb: +# +# xb expression +# or: +# xb expression_addr expression_length +# +# This does what you'd hope: +# +# mon xb +# +# but it copes with expressions for the address and length +# rather than insisting on raw numbers. +# +# xs: +# +# xs expression +# +# This does what you'd hope: +# +# mon xb +# +# would do. +# +# xv: +# +# xv expression +# +# This does what you'd hope: +# +# mon xb & sizeof() +# +# would do. use strict; use warnings; use IPC::Open3; use IO::Select; +# Store the args +my @args = @ARGV; + +# Wrap ourselves for line editing +if (!exists $ENV{'VDB_WRAPPED'}) { + `which rlwrap`; + if ($? != 0) { + print "rlwrap not available - no command line editing.\n"; + print "Consider: sudo apt-get install rlwrap\n"; + } else { + $ENV{'VDB_WRAPPED'}=1; + unshift(@args, "rlwrap", $0); + exec(@args); + } +} + # Global variables my $gdbkilled = 0; @@ -21,9 +73,6 @@ sub killgdb() { } -# Store the args -my @args = @ARGV; - # Make the invocation args for valgrind my @vgargs = ( "valgrind", @@ -61,27 +110,111 @@ $sel->add(*STDIN); *STDOUT->autoflush(); -my $scanning = 1; - +my $rate_limit = 0; sub print_lines($) { my $buf=shift; while (1) { - my $loc = index($buf, "\n"); - if ($loc < 0) { - last; + my $loc = index($buf, "\n"); + if ($loc < 0) { + last; + } + my $line = substr($buf, 0, $loc+1); + print "$line"; + $rate_limit++; + if ($rate_limit >= 24) { + sleep(1); + $rate_limit = 0; } - my $line = substr($buf, 0, $loc+1); - print "$line"; - $buf = substr($buf, $loc+1); + $buf = substr($buf, $loc+1); } return $buf; } +# We scan the output of VG to look for the magic runes +# State 0 = still waiting for magic runes +# 1 = runes have been captured. +my $vg_scan_state = 0; + +# We scan the output from GDB to look for responses to commands we have given it. +# State 0 = Normal output - just parrot it out. +# 1 = Waiting for the result of a print address +# 2 = Waiting for the result of a print length +my $gdb_scan_state = 0; + my $vgpartial = ''; my $gdbpartial = ''; +my $inpartial = ''; my $last2print = 0; # 0 = VG, 1 = GDB +my $xb_addr; +my $xb_len; +sub go_command($) { + my $command = shift; + chomp $command; + if (!defined $command) { + # When valgrind hits EOF, exit. + killgdb(); + waitpid($vgpid,0); + waitpid($gdbpid,0); + exit(0); + } elsif ($command =~ m/^\s*xb\s+(\S+)\s*$/) { + my $one = $1; + if ($one =~ m/0x[a-fA-F0-9]*/) { + $xb_addr="$one"; + $xb_len="8"; + print GDBSTDIN "mon xb $xb_addr $xb_len\n"; + } else { + # We need to figure out the value of xb_addr; + if ($one =~ m/^\&(.+)/) { + $xb_len="sizeof($1)"; + } else { + $xb_len="sizeof(*$one)"; + } + print GDBSTDIN "print $one\n"; + $gdb_scan_state=1; # Next thing we get back will be the address + } + } elsif ($command =~ m/^\s*xv\s+(\S+)\s*$/) { + my $one = $1; + # We need to figure out the value of xb_addr; + $xb_len="sizeof($one)"; + print GDBSTDIN "print &$one\n"; + $gdb_scan_state=1; # Next thing we get back will be the address + } elsif ($command =~ m/^\s*xb\s+(\S+)\s+(\S+)\s*$/) { + my $one = $1; + my $two = $2; + if ($one =~ m/0x[a-fA-F0-9]*/) { + $xb_addr="$one"; + if ($two =~ m/^\d+$/) { + $xb_len="$two"; + print GDBSTDIN "mon xb $xb_addr $xb_len\n"; + } else { + print GDBSTDIN "print $two\n"; + $gdb_scan_state=2; # Next thing we get back will be the length + } + } else { + # We need to figure out the value of xb_addr; + $xb_len="$two"; + print GDBSTDIN "print $one\n"; + $gdb_scan_state=1; # Next thing we get back will be the address + } + } elsif ($command =~ m/^\s*xs\s+(\S+)\s*$/) { + my $one = $1; + if ($one =~ m/0x[a-fA-F0-9]*/) { + $xb_addr="$one"; + print GDBSTDIN "print strlen($one)\n"; + $gdb_scan_state=2; # Next thing we get back will be the length + } else { + # We need to figure out the value of xb_addr; + $xb_len="strlen($one)"; + print GDBSTDIN "print $one\n"; + $gdb_scan_state=1; # Next thing we get back will be the address + } + } else { + print GDBSTDIN "$command\n"; + } +} + while (my @ready = $sel->can_read()) { for my $fh (@ready) { @@ -95,54 +228,117 @@ while (my @ready = $sel->can_read()) waitpid($gdbpid,0); exit(0); } - if ($scanning) { + if ($vg_scan_state == 0) { $vgbuf =~ m/(target remote \| .+ \-\-pid\=\d+)\s*/; if ($1) { - print GDBSTDIN "$1\n"; - $scanning = 0; + print GDBSTDIN "$1\n"; + $vg_scan_state = 1; } } - # It definitely read something, so print it. - if ($last2print == 1) { # Last to print was GDB + # It definitely read something, so print it. + if ($last2print == 1) { # Last to print was GDB if ($gdbpartial ne "") { # We need a newline - print "\n"; - } - # Better reprint any partial line we had - print "$vgpartial"; - } + print "\n"; + } + # Better reprint any partial line we had + print "$vgpartial"; + } $vgpartial = print_lines($vgbuf); - print "$vgpartial"; - $last2print = 0; # VG + print "$vgpartial"; + $last2print = 0; # VG } # Don't say anything to or from gdb until after we've got the magic words from valgrind - if ($scanning == 0) { - # Anything the user says, should be parotted to gdb - if ($fh eq *STDIN) { - my $buf = ''; - if (sysread(STDIN, $buf, 64*1024, length($buf)) == 0) { - # When the user hits EOF, start to kill stuff. + if ($vg_scan_state != 0) { + if ($fh eq *STDIN) { + my $inbuf=$inpartial; + if (sysread(STDIN, $inbuf, 64*1024, length($inbuf)) == 0) { + # When gdb hits EOF start to kill stuff. killgdb(); } - print GDBSTDIN "$buf"; - } + while (1) { + my $loc = index($inbuf, "\n"); + if ($loc < 0) { + last; + } + my $line = substr($inbuf, 0, $loc+1); + go_command($line); + $inbuf = substr($inbuf, $loc+1); + } + $inpartial = $inbuf; + } # Anything gdb says, should be parotted out. if ($fh eq *GDBSTDOUT) { - my $gdbbuf=''; + my $gdbbuf=''; if (sysread(GDBSTDOUT, $gdbbuf, 64*1024, length($gdbbuf)) == 0) { # When gdb hits EOF start to kill stuff. killgdb(); } - # It definite read something, so print it. - if ($last2print == 0) { # Last to print was VG - if ($vgpartial ne "") { # We need a newline - print "\n"; + while ($gdbbuf ne "") { + if ($gdb_scan_state == 0) { + # It definitely read something, so print it. + if ($last2print == 0) { # Last to print was VG + if ($vgpartial ne "") { # We need a newline + print "\n"; + } + # Better reprint any partial line we had + print "$gdbpartial"; + } + $gdbpartial = print_lines($gdbbuf); + $gdbbuf=""; + print "$gdbpartial"; + $last2print = 1; # GDB + } elsif ($gdb_scan_state == 1) { + $gdbpartial .= $gdbbuf; + $gdbbuf = ""; + while (1) { + my $loc = index($gdbpartial, "\n"); + if ($loc < 0) { + last; + } + my $line = substr($gdbpartial, 0, $loc+1); + $gdbpartial = substr($gdbpartial, $loc+1); + if ($line =~ m/\$\d+ =.*(0x[a-zA-Z0-9]+)/) { + $xb_addr=$1; + print GDBSTDIN "print $xb_len\n"; + $gdb_scan_state = 2; # Now we look for the length + last; + } + if ($line =~ m/(.*\n)/) { + $gdbpartial =~ s/(.*\n)//; + print "$1"; + $gdbbuf = $gdbpartial; + $gdbpartial = ""; + $gdb_scan_state = 0; # Error + last; + } + } + } elsif ($gdb_scan_state == 2) { + $gdbpartial .= $gdbbuf; + $gdbbuf = ""; + while (1) { + my $loc = index($gdbpartial, "\n"); + if ($loc < 0) { + last; + } + my $line = substr($gdbpartial, 0, $loc+1); + $gdbpartial = substr($gdbpartial, $loc+1); + if ($line =~ m/\$\d+ = (\d+)/) { + $xb_len=$1; + $gdb_scan_state = 0; + print GDBSTDIN "mon xb $xb_addr $xb_len\n"; + last; + } + if ($line =~ m/(.*\n)/) { + $gdbpartial =~ s/(.*\n)//; + print "$1"; + $gdbbuf = $gdbpartial; + $gdbpartial = ""; + $gdb_scan_state = 0; # Error + last; + } + } } - # Better reprint any partial line we had - print "$gdbpartial"; - } - $gdbpartial = print_lines($gdbbuf); - print "$gdbpartial"; - $last2print = 1; # GDB + } } } } -- cgit v1.2.3-65-gdbad