On Thu, May 04, 2017 at 12:54:47AM +0200, Tommaso Cucinotta wrote:
> On 03/05/2017 15:00, Scott Kostyshak wrote:
> > Tommaso, I'm still curious if you are planning to implement the gnuplot
> > patch for 2.3.0? Or perhaps you already did and I missed it?
> > 
> > The reason I ask is that time is running out to get features into 2.3.0
> > before we should focus completely on bug fixes.
> 
> I had it in my own tommaso/master branch, rebased up to last summer 
> (LinuxDay@Pisa).
> 
> I thought it was late, but as you're asking, I took the chance to rebase the 
> patch (trivial), check it's still working as expected, and push [1].
> 
> I wish someone else could try it out, in case you're short of gnuplot 
> scripts, you can use the attached sample. Just run LyX, and do 
> "Insert->Graphics...", then choose the .gp file, then enjoy the plot preview 
> on screen, as well as in the PDF formatted output.

Tommaso,

I found an old script from Koji for gnuplot. Is it useful now?

Scott
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# file gnuplot.py
# This file is an extention to LyX, the document processor.
# Licence details can be found in the file COPYING.

# \author Koji Yokota

# Full author contact details are available in file CREDITS.

# This script creates a graphic file from a Gnuplot source file.
# It is aimed to be called from external templates.
# For it to work correctly, gnuplot must be found in path.
#
#   Gnuplot: http://www.gnuplot.info/
#
# IMPORTANT!
#   gnuplot is known to have a security hole which enables execution of
#   ANY system commands from the gnuplot source file. Because of this,
#   usage of this script exposes the system to a potentially severe
#   security risk if the gnuplot source file contains a malicious code.
#   PLEASE USE THIS SCRIPT AT YOUR OWN RISK!
#
# Usage: python gnuplot.py [-t type [-o option]] [-f] \
#                          <GnuPlot source file> [<output graphics file>]
#
#        <output graphics file> is omitted either when "-s" switch
#        is specified or when "-t" switch passes "wxt", "xterm",
#        "windows" or "x11" as an argument.
#
#        -t type    terminal type
#        -o option  comma-separated options for a given terminal type
#        -s         prints out gnuplot source code to be executed to
#                   standard output without actually executing gnuplot
#        -f         allows execution of shell or load/call command
#                   from gnuplot. Note that this exposes the system to
#                   the risk thatmalicious code is executed from the
#                   gnuplot source.
#        Default values are:
#            type:   "postscript"
#            option: "eps enhanced color"
#                    (It will be reset to null once type is specified)

import re, sys, os, getopt, tempfile

class Error: pass

## comment_out() function rearranges logical lines into physical lines,
## comments out unwanted lines and prints other lines as is.
def comment_out(line_buffer):
    # line_buffer can contain multiple commands, so we separate them
    # into different lines. We want to comment out only related commands.
    # If multiple commands are in the same line, commenting out one command
    # also comments out the following commands in the same line. We want to
    # avoid this.
    # ";" is used to separate commands, but we must make sure that it
    # appears outside of quatations.
    split_buffer = find_quotations.split(line_buffer)
    # In split_buffer, (4n+3)th item is always strings in quotations,
    # (2n)th item is always quotation marks, and (4n+1)th item is strings 
    # out of quotations. So we only care about ";" in (4n+1)th item.
    for i in range(len(split_buffer)):
        if i % 4 == 0 and find_separator.search(split_buffer[i]):
            # Replace ';' with '\n' in strings outside of quotations
            split_buffer[i] = \
                find_extra_space.sub(
                    r'\1', find_separator.sub(r'\n', split_buffer[i]))
    # Reset line_buffer to restructure it from the list split_buffer
    line_buffer = ''
    for i in range(0,len(split_buffer)-1):
        line_buffer = line_buffer + split_buffer[i]
    line_buffer = line_buffer + split_buffer[len(split_buffer)-1]
    # As line_buffer is restructured so that a logical line corresponds
    # to a physical line, we can safely comment out unwanted commands.
    if find_terminal.search(line_buffer):
        line_buffer = find_terminal.sub(r'# \1', line_buffer)
        count_terminal = 1
    if find_output.search(line_buffer):
        line_buffer = find_output.sub(r'# \1', line_buffer)
        count_output = 1
    if not allow_shell_execution and find_shell_execution.search(line_buffer):
        line_buffer = find_shell_execution.sub(r'# \1', line_buffer)
    print line_buffer

def print_help(script_name):
    print '\n' + script_name
    print '\nThis script outputs a graphics file from a Gnuplot source file.\n'
    print 'Usage:\n    python ' + script_name + ' [-t type [-o option]] \\'
    print '              [-s] [-f] <gnuplot source file> [<output graphics 
file>]'
    print '    python ' + script_name + ' -h\n'
    print '        <output graphics file> is omitted either when "-s" switch'
    print '        is specified or when "-t" switch passes "wxt", "xterm",'
    print '        "windows" or "x11" as an argument.\n'
    print '        -t type   terminal type (see "help terminal" in gnuplot for'
    print '                  available values)'
    print '        -o option comma-separated options for a given terminal type'
    print '                  (see "help terminal <terminal type>" in gnuplot 
for'
    print '                   available values)'
    print '        -s        prints out gnuplot source code to be executed to'
    print '                  standard output without actually executing gnuplot'
    print '        -f        allows execution of shell or load/call command'
    print '                  from gnuplot. Note that this exposes the system to'
    print '                  the risk that malicious code is executed from the'
    print '                  gnuplot source.'
    print '        -h        prints this help message.'
    print '\n        Default values are:'
    print '            type:   "postscript"'
    print '            option: "eps enhanced color" (It will be reset to null'
    print '                     once type is specified)\n'

#
# Get options and arguments
#
opts, args = getopt.getopt(sys.argv[1:], "t:o:sfh")

# Set output graphic type and options
# It's very likely that terminal type and its options are set for review
# purpose (e.g. wxt) or else. This script automates specification of
# output format.
terminal_type = 'postscript'
terminal_option = ['eps', 'enhanced', 'color']
type_specified = 0
option_specified = 0
allow_shell_execution = 0
print_source_code = 0
output_to_screen = 0
for o,v in opts:
    if o == '-h':
        print_help(sys.argv[0])
        sys.exit(0)
    elif o == '-t':
        terminal_type = v
        type_specified = 1
        if v == 'wxt' or v == 'xterm' or v == 'windows' or v == 'x11':
                output_to_screen = 1
    elif o == '-o':
        terminal_option = v.split(',')
        option_specified = 1
    elif o == '-f':
        allow_shell_execution = 1
    elif o == '-s':
        print_source_code = 1
        output_to_screen = 1
if type_specified and not option_specified:
    terminal_option = []
try:
    if output_to_screen != 1 and len(args) != 2:
        raise Error()
    elif output_to_screen == 1 and len(args) != 1:
        raise Error()
except Error:
    print_help(sys.argv[0])
    sys.exit(1)

# Set "set terminal" and "set output" lines used for output
terminal_line = 'set terminal ' + terminal_type
if terminal_option != []:
    for o in terminal_option:
        terminal_line = terminal_line + ' ' + o
if output_to_screen != 1:
    output_line = 'set output "' + args[1] + '"'

# Definition of strings to be replaced
find_terminal = re.compile(r'^(\s*set\s+terminal.*)',re.MULTILINE)
find_output = re.compile(r'^(\s*set\s+output.*)',re.MULTILINE)
find_comment = re.compile(r'(^#|^\s*$)')
find_multiple_lines = re.compile(r'\\$',re.MULTILINE)
find_quotations = re.compile(r'([\'\"])')
find_separator = re.compile(r';')
find_extra_space = re.compile(r'(^)\s+',re.MULTILINE)
if not allow_shell_execution:
    find_shell_execution = 
re.compile(r'^(([^#\'\"]*system\s*\(|\s*(system|\!|load|call)).*)',re.MULTILINE)

# 
# Construction of Gnuplot source code
#
# Open a temporary file for a modified source if '-s' is not specified
# in the command line option
if not print_source_code:
    tmp_filename = tempfile.mktemp('.gnuplot')
    tmp_file = open(tmp_filename, 'w')
    sys.stdout = tmp_file
# Flag to show whether the header comment part is finished
comment_ended = 0
# line_buffer is used to store multiple lines to concatenate physical lines
line_buffer = ''

# Modify and output lines one by one
for line in open(args[0]):
    # Concatenate physical lines as far as a line finishes with a slash
    # and store them in line_buffer.
    # line contains '\n' at the end, which is eliminated by [:-1].
    line_buffer = line_buffer + line[:-1]
    if find_multiple_lines.search(line):
        line_buffer = find_multiple_lines.sub('',line_buffer)
        continue
    # gnuplot source files can have header comments.
    # After those header comments (paranoid), we insert new
    # 'set terminal...' and 'set output' lines appropriate for lyx and
    # comment out the original lines.
    if comment_ended == 1:
        comment_out(line_buffer)
    else:
        if not find_comment.search(line_buffer):
            # This is the first line after the comment part
            # Insert new 'set terminal' and 'set output'
            print terminal_line
            if output_to_screen != 1:
                print output_line
            comment_out(line_buffer)
            comment_ended = 1
        else:
            # Comment part still continues, just output lines
            print line_buffer
    # Reset line_buffer
    line_buffer = ''

#
# Execution of Gnuplot
#
# If '-s' command-line option is not given, execute gnuplot
if not print_source_code:
    # Closing the temporary file
    tmp_file.close()
    # Execute gnuplot to generate a graphics file from the source
    try:
        if output_to_screen == 1:
            os.system('gnuplot -p %(tmp_filename)s' % vars())
        else:
            os.system('gnuplot %(tmp_filename)s' % vars())
    finally:
        # Remove the temporary file
        #os.remove(tmp_filename)
        sys.exit(0)

Attachment: signature.asc
Description: PGP signature

Reply via email to