diff options
author | bwarken <bwarken> | 2013-03-02 23:53:32 +0000 |
---|---|---|
committer | bwarken <bwarken> | 2013-03-02 23:53:32 +0000 |
commit | a91c15abeeec7814deba46bfa51f9c4aac947903 (patch) | |
tree | 378548f796305f4974221bc0e4ad483c0a29b61e /contrib | |
parent | db9a2079f7c26034bb088f82a0d7ec7a8fd0cb7e (diff) | |
download | groff-a91c15abeeec7814deba46bfa51f9c4aac947903.tar.gz |
Publishing groff_lilypond version v0.5.
New code with Perl references.
New options: --usage, -V|--Verbose|--verbose, --file_prefix=...,
-o|--output=..., --temp_dir=...
Perl >=5.10.0 needed.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/lilypond/ChangeLog | 9 | ||||
-rw-r--r-- | contrib/lilypond/groff_lilypond.man | 29 | ||||
-rwxr-xr-x | contrib/lilypond/groff_lilypond.pl | 1185 |
3 files changed, 838 insertions, 385 deletions
diff --git a/contrib/lilypond/ChangeLog b/contrib/lilypond/ChangeLog index 6dae5162..c9f96d85 100644 --- a/contrib/lilypond/ChangeLog +++ b/contrib/lilypond/ChangeLog @@ -1,3 +1,12 @@ +2013-03-03 Bernd Warken <groff-bernd.warken-72@web.de> + + * groff_lilypond.pl: New code with Perl references. + Publishing groff_lilypond version v0.5. + New options: --usage, -V|--Verbose|--verbose, --file_prefix=..., + -o|--output=..., --temp_dir=... + Perl >=5.10.0 needed. + * groff_lilypond.man: Include the new options. + 2013-02-23 Bernd Warken <groff-bernd.warken-72@web.de> * groff_lilypond_pl: Remove `.lilypond include' for lilypond diff --git a/contrib/lilypond/groff_lilypond.man b/contrib/lilypond/groff_lilypond.man index 0c6a4198..3cbc1a0f 100644 --- a/contrib/lilypond/groff_lilypond.man +++ b/contrib/lilypond/groff_lilypond.man @@ -13,7 +13,7 @@ This file was written by Bernd Warken .MT groff\-bernd.warken\-72@web.de .ME . . -Last update: 22 Feb 2013 +Last update: 03 Mar 2013 .. . . @@ -200,7 +200,7 @@ stands for standard input. .P .SY .OP -h\~\fR|\fB\~--help -.OP -v\~\fR|\fB\~--version +.OP -v\~\fR|\fB\~--version\fR|\fB\~--usage .OP \fB\~--license .YS .RE @@ -272,6 +272,29 @@ No extensions are used for this directory. . If the directory does not exist it will be created. . +.RE +. +. +.TP +.I \%output +.RS +. +. +.TP +.OP -o\fR|\fB\~--output file_name +Normally all +.FONT CI groff +output is sent to +FONT CB STDOUT R . +. +With this option that can be stored in a +.IR file . +. +. +.TP +.OP -V\~\fR|\fB\~--Verbose|\fB\~--verbose +A lot more of output is sent to STDERR. +. . .RE . @@ -499,7 +522,7 @@ command . . .\" -------------------------------------------------------------------- -.SH "NEW ROFF STRUCTURE" +.SH "THE GENERATED NEW ROFF STRUCTURE" .\" -------------------------------------------------------------------- . The new diff --git a/contrib/lilypond/groff_lilypond.pl b/contrib/lilypond/groff_lilypond.pl index c02f23ab..8e2a3479 100755 --- a/contrib/lilypond/groff_lilypond.pl +++ b/contrib/lilypond/groff_lilypond.pl @@ -1,45 +1,52 @@ #! /usr/bin/env perl use strict; +use 5.10.0; + # use warnings; + ######################################################################## # legalese ######################################################################## -my $Version = 'v0.4'; # version of groff_lilypond -my $LastUpdate = '23 Feb 2013'; +{ + package main; + use strict; + + use vars '$VERSION'; + $VERSION = 'v0.5'; # version of groff_lilypond + $main::last_update = '03 Mar 2013'; -my $License = ### `$License' is the license for this file, `GPL' >= 3 -' -groff_lilypond - integrate lilypond into groff files + ### This `$License' is the license for this file, `GPL' >= 3 + $main::License = q* +groff_lilypond - integrate `lilypond' into `groff' files -Source file position: <groff-source>/contrib/lilypond/groff_lilypond.pl -Installed position: <prefix>/bin/groff_lilypond +Source file position: `<groff-source>/contrib/lilypond/groff_lilypond.pl' +Installed position: `<prefix>/bin/groff_lilypond' Copyright (C) 2013 Free Software Foundation, Inc. Written by Bernd Warken <groff-bernd.warken-72@web.de> -This file is part of GNU groff. +This file is part of `GNU groff'. - GNU groff is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation, either version 3 of the License, or (at your + `GNU groff' is free software: you can redistribute it and/or modify it +under the terms of the `GNU General Public License' as published by the +`Free Software Foundation', either version 3 of the License, or (at your option) any later version. - GNU groff is distributed in the hope that it will be useful, but + `GNU groff' is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - - You should have received a copy of the GNU General Public License -along with groff, see the files COPYING and LICENSE in the top -directory of the groff source package. If not, see - http://www.gnu.org/licenses/>. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the `GNU +General Public License' for more details. -'; + You should have received a copy of the 'GNU General Public License` +along with `groff', see the files `COPYING' and `LICENSE' in the top +directory of the `groff' source package. If not, see +<http://www.gnu.org/licenses/>. +*; ##### end legalese @@ -48,37 +55,38 @@ directory of the groff source package. If not, see # global variables ######################################################################## -use File::Spec; -use File::Path qw[]; -use Cwd qw[]; - - -# `$IsInstalled' is 1 if groff is installed, 0 when in source package -my $IsInstalled = ( '@VERSION@' =~ /^[@]VERSION[@]$/ ) ? 0 : 1; + use File::Spec qw[]; + use File::Path qw[]; + use Time::HiRes qw[]; + use constant FALSE => 0; + use constant TRUE => 1; + use constant EMPTYSTRING => ''; + use constant EMPTYARRAY => (); + use constant EMPTYHASH => (); -my $Prog = &get_prog_name; + $main::at_version_at = '@VERSION@'; # @...@ is replaced for the installation -my $GroffVersion = ''; # when not installed -$GroffVersion = '@VERSION@' if ( $IsInstalled ); # @...@ was replaced + # `$prog_is_installed' is TRUE if groff is installed, + # FALSE when in source package + $main::prog_is_installed = ( $main::at_version_at =~ /^[@]VERSION[@]$/ ) + ? FALSE : TRUE; + { + ( my $v, my $d, $main::prog) = File::Spec->splitpath($0); + } + # is `groff_lilypond' when installed, `groff_lilypond.pl' when not -# command line arguments -my $EpsMode = 'ly2eps'; # default -my $KeepFiles = 0; + $main::groff_version = $main::prog_is_installed + ? $main::at_version_at : main::EMPTYSTRING; -my $TempDir = ''; # temporary directory -my $FilePrefix = 'ly'; # names of temporary files start with this + $\ = "\n"; # adds newline at each print -# read files or stdin -my $FilePrefix; # `$TempDir/ly_' -my $FileNumbered; # `$FilePrefix_[0-9]' -my $FileLy; # `$FileNumbered.ly' - -# `§Cwd' stores the current directory -my $Cwd = Cwd::getcwd; # get current working directory + $main::fh_verbose; # file handle only for `--verbose' + $main::fh_out; # file handle for `--output' +} # end of package `main' ##### end global variables @@ -88,218 +96,483 @@ my $Cwd = Cwd::getcwd; # get current working directory ######################################################################## { - my $double_minus = 0; - my @FILES = (); + package Args; + use strict; + + # command line arguments + $Args::keep_files = main::FALSE; + + # default `--ly2eps', another `--pdf2eps' + $Args::eps_func = 'ly2eps'; + + $Args::temp_dir = main::EMPTYSTRING; # temporary directory + # can be overwritten by `--temp_dir' + + $Args::file_prefix = 'ly'; + # names of temporary files in $main::TempDir start with this string + # can be overwritten by `--file_prefix' + + $Args::verbose = main::FALSE; + $Args::output = $1; + + + my $double_minus = main::FALSE; + my @args = main::EMPTYARRAY; + + { + my %single_opts = + ( + 'h' => main::FALSE, + 'o' => main::TRUE, # has argument + 'v' => main::FALSE, + 'V' => main::FALSE, + ); + + my @splitted_args; - my $has_arg = ''; - my $former_arg = ''; # for options with argument - my $arg = ''; # needed here for subs + SINGLE: foreach (@ARGV) { + + if ( $double_minus ) { + push @splitted_args, $_; + next SINGLE; + } + + s/^\s*(.*)\s*$/$1/; # remove leading and final spaces + + if ( /^--$/ ) { # `--' + push @splitted_args, $_; + $double_minus = main::TRUE; + next SINGLE; + } + + if ( /^--/ ) { + if ( /=/ ) { # `--opt' with `=' for arg + /^([^=]*)=(.*)$/; + push @splitted_args, $1; + push @splitted_args, $2; + next SINGLE; + } + push @splitted_args, $_; + next SINGLE; + } + + if ( /^-([^-].*)$/ ) { # single minus + my @chars = split //, $1; + while ( @chars ) { + my $c = shift @chars; + if ( exists $single_opts{ $c } ) { + push @splitted_args, "-" . $c; + next SINGLE unless ( $single_opts{ $c } ); # opt without arg + + # single opt with arg + my $opt_arg = join '', @chars; + push @splitted_args, $opt_arg; + @chars = main::EMPTYARRAY; + next SINGLE + } else { # not in %single_opts + print STDERR "Unknown option `-$c'"; + } + } + } + + push @splitted_args, $_; + next SINGLE; + } + + @ARGV = @splitted_args; + + } + $double_minus = main::FALSE; + + + # arguments are splitted + + + my $has_arg; + my $arg; + my $former_arg; + my $exit = main::FALSE; + my @files; + + + my %only_minus = + ( + '-' => sub { push @files, '-'; }, + '--' => sub { push @args, '--'; $double_minus = main::TRUE; }, + ); - my %only_minus = ( - '-' => sub { push @FILES, '-'; }, - '--' => sub { $double_minus = 1; }, - ); my @opt; - $opt[2] = { # option abbreviations of 2 characters - '-h' => sub { &usage; exit; }, # `-h' - '-v' => sub { &version; exit; }, # `-v' - }; - - - $opt[3] = { # option abbreviations of 3 characters - '--f' => sub { # `--file_prefix' - if ( $arg =~ /^.*=(.*)$/ ) { # opt arg is within $arg - $FilePrefix = $1; - } else { # opt arg is the next command line argument - $has_arg = '--file_prefix'; - } # end if for `=' - next ARGS; - }, # end `--file_prefix' - - '--h' => sub { &usage; exit; }, # `--help' - '--v' => sub { &version; exit; }, # `--version' - '--k' => sub { $KeepFiles = 1; next ARGS; }, # `--keep_files' - '--p' => sub { $EpsMode = 'pdf2eps'; next ARGS; }, # `--pdf2eps' - - '--t' => sub { # `--temp_dir' - if ( $arg =~ /^.*=(.*)$/ ) { - my $dir = $1; - $dir =~ s/^\s*(.*)\s*$/$1/; - my $res = &make_dir ( $dir ) or - die "The directory $dir cannot be used.\n"; - $TempDir = $res; - } else { # next command line argument is the option argument - $has_arg = '--temp_dir'; - } # end if for `=' - next ARGS; - }, # end sub of `--t' - - }; # end `$opt[3]' - - - $opt[4] = { # option abbreviations of 4 characters - '--li' => sub { &license; exit; }, - '--ly' => sub { $EpsMode = 'ly2eps'; next ARGS; }, - }; - - sub check_arg { # is used in `ARGS forever + $opt[2] = + { # option abbreviations of 2 characters + + '-h' => sub { + &Subs::usage; + push @args, '--help'; + $exit = main::TRUE; + }, # `-h' + + '-o' => sub { # `-o' + $has_arg = '--output'; + $former_arg = $has_arg; + next ARGS; + }, + + '-v' => sub { # `-v' + &Subs::version; + push @args, '--version'; + $exit = main::TRUE; + next ARGS; + }, + + '-V' => sub { # `-V' + $Args::verbose = main::TRUE; + push @args, '--verbose'; + next ARGS; + }, + + }; + + + $opt[3] = + { # option abbreviations of 3 characters + + '--f' => sub { # `--file_prefix' + $has_arg = '--file_prefix'; + $former_arg = $has_arg; + next ARGS; + }, # end `--file_prefix' + + '--h' => sub { # `--help' + &Subs::usage; + push @args, '--help'; + $exit = main::TRUE; + }, + + '--k' => sub { # `--keep_files' + $Args::keep_files = main::TRUE; + push @args, '--keep_files'; + next ARGS; + }, + + '--o' => sub { # `--output' + # next command line argument is the option argument + $has_arg = '--output'; + $former_arg = $has_arg; + next ARGS; + }, # end sub of `--o' + + # `--pdf2eps' + '--p' => sub { + $Args::eps_func = 'pdf2eps'; + push @args, '--pdf2eps'; + next ARGS; + }, + + '--t' => sub { # `--temp_dir' + # next command line argument is the option argument + $has_arg = '--temp_dir'; + $former_arg = $has_arg; + next ARGS; + }, # end sub of `--t' + + '--u' => sub { + &Subs::usage; + push @args, '--help'; + $exit = main::TRUE; + }, # `--usage' + + '--V' => sub { # `--Verbose' + $Args::verbose = main::TRUE; + push @args, '--verbose'; + next ARGS; }, + + }; # end `$opt[3]' + + + $opt[4] = + { # option abbreviations of 4 characters + + '--li' => sub { # `--license' + &Subs::license; + push @args, '--license'; + $exit = main::TRUE; + }, + + '--ly' => sub { # `--ly2eps' + $Args::eps_func = 'ly2eps'; + push @args, '--ly2eps'; + next ARGS; + }, + }; + + + $opt[6] = + { # option abbreviations of 6 characters + + '--verb' => sub { # `--verbose' + $Args::verbose = main::TRUE; + push @args, '--verbose'; + next ARGS; + }, + + '--vers' => sub { # `--version' + &Subs::version; + push @args, '==version'; + $exit = main::TRUE; + }, + + }; + + + # for optarg that is a complete argument + my $arg_is_optarg = + { + + '--file_prefix' => sub { + $Args::file_prefix = $arg; + }, + + '--output' => sub { + die "file name expected for option `--output'" + unless ( $arg ); + $Args::output = $arg; + }, + + '--temp_dir' => sub { + $Args::temp_dir = $arg; + }, + + }; + + + my $check_arg = sub { # is used in `ARGS:' foreach # 2 arguments: # - content of $arg - # - a number between 2 and 4 - my ( $arg, $n ) = @_; + # - a number of 2, 3, 4, or 6 + my ( $from_arg, $n ) = @_; my $re = qr/^(.{$n})/; - if ( $arg =~ $re ) { - my $arg = $1; - if ( exists $opt[ $n ]-> { $arg } ) { - &{ $opt[ $n ] -> { $arg } }; - next ARGS; # for running `next' - } - } - } + if ( $from_arg =~ $re ) { + $from_arg = $1; + if ( exists $opt[ $n ]-> { $from_arg } ) { + &{ $opt[ $n ] -> { $from_arg } }; + next ARGS; + } # end exists + } # end match $n characters + }; # end sub check_args() - ARGS: foreach (@ARGV) { + ARGS: foreach ( @ARGV ) { chomp; s/^\s*(.*)\s*$/$1/; $arg = $_; - if ( $has_arg ) { - # only `--temp_dir' and `--file_prefix' expect an argument + # former option needs this argument as optarg + if ( exists $arg_is_optarg -> { $has_arg } ) { + &{ $arg_is_optarg -> { $has_arg } }; + push @args, $former_arg . " " . $arg; + $has_arg = main::EMPTYSTRING; + $former_arg = main::EMPTYSTRING; + next ARGS; + } - if ( $has_arg eq '--temp_dir' ) { - my $dir = &make_dir ( $arg ) or - die "The directory $arg cannot be used.\n"; - $TempDir = $dir; - $has_arg = ''; + if ( $double_minus # `--' was former arg + or $arg =~ /^[^-].*$/ ) { # arg is a file name without `-' + push @files, $arg; next ARGS; - } + } # after integration of file arg - if ( $has_arg eq '--file_prefix' ) { - $FilePrefix = $arg; - $has_arg = ''; - next ARGS; - } - die "Wrong value for \$has_arg"; + # now only args with starting '-' + + if ( exists $only_minus{ $arg } ) { + &{ $only_minus{ $arg } }; + next ARGS; } + # deal with @opt + &$check_arg( $arg, $_ ) foreach ( qw[ 6 4 3 2 ] ); - if ( $double_minus ) { # `--' was former arg - push @FILES, $arg; - next; - } # file arg after -- + # wrong argument + print STDERR "Wrong argument for groff_lilypond: `$arg'"; + next ARGS; - if ( $arg =~ /^[^-].*$/ ) { # arg is a file name without `-' - push @FILES, $arg; - next; - } + } # end ARGS: foreach @ARGV - # now only args with starting '-' - if ( exists $only_minus { $arg } ) { - &{ $only_minus { $arg } }; - next; + if ( $has_arg ) { # after last argument + die "Option `$has_arg' needs an argument."; + } + + + # install `$main::fh_verbose' + if ( $Args::verbose ) { # `--verbose' was used + # make verbose output, i.e. make `$main::fh_verbose' visible + $main::fh_verbose = *STDERR; + + } else { # `--verbose' was not used + # do not be verbose, make `$main::fh_verbose' invisible, e.g. either + # in /dev/null or in a string + + my $opened = main::FALSE; + my $null = '/dev/null'; + + if ( -e $null && -w $null ) { + open $main::fh_verbose, ">", $null or + die "Could not open `$null': $!"; + + # `/dev/null' will now be used for verbose output + $opened = main::TRUE; } - # deal with @opt - &check_arg ( $arg, $_ ) foreach ( qw[ 4 3 2 ] ); + unless ( $opened ) { # couldn't use /dev/null, so print into a string + my $print_to_string; + open $main::fh_verbose, ">", \ $print_to_string or + die "Could not open `\$main::fh_verbose': $!"; + # now verbose output will go into a string, which is ignored + } + } # if-else about verbose + # $main::fh_verbose is now active - # wrong argument - print STDERR "Wrong argument for groff_lilypond: $_\n"; - next; + { + my $s = $main::prog_is_installed ? '' : ' not'; + print $main::fh_verbose "$main::prog is$s installed."; + print $main::fh_verbose 'The command line options are:'; + print $main::fh_verbose " @args"; + print $main::fh_verbose "files: @files"; + } - } # end ARGS: foreach @ARGV + exit if ( $exit ); - if ( $has_arg ) { - print STDERR "Option --temp_dir needs an argument.\n"; + + if ( $Args::output ) { + open $main::fh_out, ">", $Args::output or + die "could not write to `$Args::output': $!"; + } else { + $main::fh_out = *STDOUT; } - @ARGV = @FILES; + $Args::file_prefix .= '_' . $Args::eps_func; + + + @ARGV = @files; } -# end command line arguments +# end package `Args' ######################################################################## # temporary directory .../tmp/groff/USER/lilypond/TIME ######################################################################## -unless ( "$TempDir" ) { # not given by `--temp_dir' +{ + package Temp; + use strict; - my $home; - { - $home = $ENV{'HOME'}; - $home =~ s(/*$)(/tmp); - } + use Cwd qw[]; + # `$Cwd' stores the current directory + ( $Temp::Cwd = Cwd::getcwd ) =~ s</*$></>; # add final slash - my $cwd; - { - $cwd = $Cwd; # current working directory - $cwd =~ s(/*$)(/tmp); - } + if ( $Args::temp_dir ) { # temporary directory was set by `--temp_dir' + my $dir = $Args::temp_dir; + unless ( $dir =~ m<^/> ) { # not starting with a slash + $dir = $Temp::Cwd . $dir; + } - my $user = $ENV{'USER'}; - { - $user =~ s([\s/])()g; - } + # now $dir starts with a slash + $dir =~ s{/*$}{/}; + if ( -e $dir ) { + die "Could not write to temporary directory: $dir" + unless ( -w $dir ); + unless ( -d $dir ) { + unlink $dir; + die "Could not remove $dir" if ( -e $dir ); + } + } - use Time::HiRes qw[]; + if ( -d $dir ) { # is a directory + my $files = glob $dir . $Args::file_prefix . "_*"; + $Args::file_prefix .= "_" . &Subs::dir_time if ( $files ); + } else { # not a directory + my $dir = &Subs::make_dir ( $dir ) or + die "The directory $dir cannot be used."; + } + $Args::temp_dir = $dir; - { # search for or create a temporary directory - my $path_extension = '/groff/'; - $path_extension .= $user. '/' if ($user); - $path_extension .= 'lilypond/'; + } else { # $Args::temp_dir not given by `--temp_dir' + { # search for or create a temporary directory - my @temp_dirs = ('/tmp', $home, $cwd); - foreach (@temp_dirs) { + my $path_extension = 'groff/'; + { + ( my $user = $ENV{ 'USER' } ) =~ s([\s/])()g; + $path_extension .= $user. '/' if ($user); + } + $path_extension .= 'lilypond/'; - my $dir_begin = $_ . $path_extension; # beginning of directory name - my $dir_free = 0; # `1' when directory not exists, free for creating - my $dir; #final directory name in `until' loop - until ( $dir_free ) { - $dir = $dir_begin . &dir_time; - if ( -d $dir ) { - Time::HiRes::usleep(1); # wait 1 microsecond - } else { - my $res = &make_dir( $dir ); - $dir = $res; - $dir_free = 1; - } - } + ( my $home = $ENV{'HOME'} ) =~ s(/*$)(/); - next unless ( -d $dir && -w $dir ); + TEMPS: foreach ( '/', $home, $Temp::Cwd ) { + # temorary dirs by appending `tmp/' - $TempDir = $dir; # tmp/groff/USER/lilypond/TIME - last; - } # end foreach tmp directories - } # end to create a temporary directory -} # end temporary directory -$TempDir =~ s(/*$)(/); + # beginning of directory name + my $dir_begin = $_ . 'tmp/' . $path_extension; -print STDERR "Temporary directory: $TempDir\n"; + # `TRUE' when dir doesn't exist, free for creating + my $dir; # final directory name in `until' loop + my $dir_blocked = main::TRUE; + BLOCK: while ( $dir_blocked ) { + # should become the final dir name + $dir = $dir_begin . &Subs::dir_time; + if ( -d $dir ) { # dir exists, so wait + Time::HiRes::usleep(1); # wait 1 microsecond + next BLOCK; + } -# end temporary directory + # dir name is now free, create it, and end the blocking + my $res = &Subs::make_dir( $dir ); + die "Could not create directory: $dir" unless ( $res ); + + $dir = $res; + $dir_blocked = main::FALSE; + } + + next TEMPS unless ( -d $dir && -w $dir ); + + $Args::temp_dir = $dir; # tmp/groff/USER/lilypond/TIME + last TEMPS; + } # end foreach tmp directories + } # end to create a temporary directory + + $Args::temp_dir =~ s(/*$)(/); + + } # end temporary directory + + print $main::fh_verbose "Temporary directory: `$Args::temp_dir'"; + print $main::fh_verbose "file_prefix: `$Args::file_prefix'"; + +} + +# end package `Temp' ######################################################################## @@ -307,306 +580,454 @@ print STDERR "Temporary directory: $TempDir\n"; ######################################################################## { # read files or stdin - my $ly_number = 0; - my $lilypond_mode = 0; - my $arg1 = ''; # first argument for `.lilypond' - my $arg2 = ''; # argument for `.lilypond include' + package Read; + use strict; - $FilePrefix = $TempDir . $FilePrefix . '_'; + my $ly_number = 0; # number of lilypond file - my %lilypond_args = ( + # `$Args::file_prefix_[0-9]' + $Read::file_numbered = main::EMPTYSTRING; + $Read::file_ly = main::EMPTYSTRING; # `$file_numbered.ly' - 'start' => sub { - die "Line `.lilypond stop' expected." - if ($lilypond_mode); - $lilypond_mode = 1; - $ly_number++; - $FileNumbered = $FilePrefix . $ly_number; - $FileLy = $FileNumbered . '.ly'; - open FILELY, ">", $FileLy or - die "cannot open *.ly file: $!"; - next LILYPOND; - }, + my $lilypond_mode = main::FALSE; + my $arg1; # first argument for `.lilypond' + my $arg2; # argument for `.lilypond include' - 'end' => sub { - die "Line `.lilypond start' expected." - unless ( $lilypond_mode ); - $lilypond_mode = 0; - close FILELY; - &create_eps; - next LILYPOND; - }, + my $check_file = sub { # for argument of `.lilypond include' + my $file = shift; + unless ( $file ) { + die "Line `.lilypond include' without argument"; + return '';; + } + unless ( -f $file && -r $file ) { + die "Argument `$file' in `.lilypond include' is not a readable file"; + return main::EMPTYSTRING; + } + return $file; + }; # end sub &$check_file() - 'include' => sub { # `.lilypond include file...' + my $increase_ly_number = sub { + ++$ly_number; + $Read::file_numbered = $Args::file_prefix . '_' . $ly_number; + $Read::file_ly = $Read::file_numbered . '.ly'; + }; - # this may not be used within lilypond mode - next LILYPOND if ( $lilypond_mode ); - my $file = &check_file( $arg2 ); - next LILYPOND unless ( $file ); - # file can be read now + my %eps_subs = ( + 'ly2eps' => \&Subs::create_ly2eps, + 'pdf2eps' => \&Subs::create_pdf2eps, + ); - # FILELY must be opened - $ly_number++; - $FileNumbered = $FilePrefix . $ly_number; - $FileLy = $FileNumbered . '.ly'; + # about lines starting with `.lilypobnd' - open FILELY, ">", $FileLy or - die "cannot open `$FileLy' file: $!"; + my $fh_write_ly; + my $fh_include_file; + my %lilypond_args = + ( - open FILE, "<", $file # for reading - or die "File `$file' could not be read: $!"; - foreach (<FILE>) { - chomp; - print FILELY $_ . "\n"; - } - close FILE; + 'start' => sub { + print $main::fh_verbose "line: `.lilypond start'"; + die "Line `.lilypond stop' expected." if ( $lilypond_mode ); - close FILELY; - &create_eps; + $lilypond_mode = main::TRUE; + &$increase_ly_number; - next LILYPOND; - }, # end `.lilypond include' + print $main::fh_verbose + "ly-file: `" . $Args::temp_dir . $Read::file_ly . "'"; - ); # end definition %lilypond_args + open $fh_write_ly, ">", $Args::temp_dir . $Read::file_ly or + die "Cannot open file `$Args::temp_dir$Read::file_ly': $!"; + next LILYPOND; + }, - sub check_file { # for argument of `.lilypond include' - my $file = shift; + 'end' => sub { + print $main::fh_verbose "line: `.lilypond end'"; + die "Expected line `.lilypond start'." unless ( $lilypond_mode ); - unless ( $file ) { - print STDERR - 'Line ".lilypond include" without argument'; - return '';; - } + $lilypond_mode = main::FALSE; + close $fh_write_ly; - unless ( -f $file && -r $file ) { - print STDERR 'Argument "' . $file . - '" in ".lilypond include" ' . - 'is not a readable file' . "\n"; - return ''; - } + if ( exists $eps_subs{ $Args::eps_func } ) { + $eps_subs{ $Args::eps_func } -> (); + } else { + die "Wrong argument for \%eps_subs: $Args::eps_func"; + } + next LILYPOND; + }, + + + 'include' => sub { # `.lilypond include file...' + + # this may not be used within lilypond mode + next LILYPOND if ( $lilypond_mode ); + + my $file_arg = shift; + + my $file = &$check_file( $file_arg ); + next LILYPOND unless ( $file ); + # file can be read now + + # `$fh_write_ly' must be opened + &$increase_ly_number; + + open $fh_write_ly, ">", $Args::temp_dir . $Read::file_ly or + die "Cannot open file `$Read::file_ly': $!"; + + open $fh_include_file, "<", $file # for reading + or die "File `$file' could not be read: $!"; + foreach (<$fh_include_file>) { + chomp; + print $fh_write_ly $_; + } + close $fh_include_file; + + close $fh_write_ly; + if ( exists $eps_subs{ $Args::eps_func } ) { + $eps_subs{ $Args::eps_func } -> (); + } else { + die "Wrong argument for \$eps_subs: $Args::eps_func"; + } + + next LILYPOND; + }, # end `.lilypond include' + + ); # end definition %lilypond_args - return $file; - } # end sub check_file() LILYPOND: foreach (<>) { chomp; - my $line = $_; # now the lines with '.lilypond ...' - if ( /^[.']\s*lilypond\s*(.*)\s*(.*)\s*$/ ) { # .lilypond ... - my $arg1 = $1; - my $arg2 = $2; + if ( /^[.']\s*lilypond(.*)$/ ) { # .lilypond ... + my $args = $1; + $args =~ s/^\s*//; + $args =~ s/\s*$//; + $args =~ s/^(\S*)\s*//; + my $arg1 = $1; # `start', `end' or `include' + $args =~ s/["'`]//g; + my $arg2 = $args; # file argument for `.lilypond include' if ( exists $lilypond_args{ $arg1 } ) { - & { $lilypond_args{ $arg1 } } + $lilypond_args{ $arg1 } -> ( $arg2 ); } else { # not a suitable argument of `.lilypond' - print $_ . "\n"; + print STDERR "Unknown command: `$arg1' `$arg2': `$_'"; } next LILYPOND; + } # end if .lilypond - } if ( $lilypond_mode ) { # do lilypond-mode - print FILELY $line . "\n" or # see `.lilypond start' - die "could not print to FILELY in lilypond-mode\n"; + print $fh_write_ly $line or # see `.lilypond start' + die "could not print to \$fh_write_ly in lilypond-mode"; next LILYPOND; } # do lilypond-mode # unknown line without lilypond unless ( /^[.']\s*lilypond/ ) { # not a `.lilypond' line - print $line . "\n"; # to STDOUT + print $main::fh_out $line; next LILYPOND; } - } # end foreach <> -} # end read files or stdin +} # end package Read + + +######################################################################## +# clean up +######################################################################## + +{ + package Clean; + use strict; + + + # With --keep_files, no temporary files are removed. + if ( $Args::keep_files ) { + print $main::fh_verbose "keep_files: `TRUE'"; + print $main::fh_verbose "No temporary files will be deleted:"; + opendir my $dh_temp, $Args::temp_dir or + die "Cannot open $Args::temp_dir: $!"; -# Remove all temporary files except the eps files. -# With --keep_files, no files are removed. -unlink glob $FilePrefix . "*.[a-df-z]*" unless $KeepFiles; + for ( sort readdir $dh_temp ) { + next if ( /^\./ ); + my $prefix = $Args::file_prefix . '_'; + my $re = qr/^$prefix/; + if ( $_ =~ $re ) { + print $main::fh_verbose "- " . $Args::temp_dir . $_; + next; + } + next; + } -# end read files and stdin + closedir $dh_temp; + } else { + # Remove all temporary files except the eps files. + print $main::fh_verbose "keep_files: `FALSE'"; + print $main::fh_verbose + "All temporary files except *.eps will be deleted"; + + unlink glob $Args::temp_dir . $Args::file_prefix . "*.[a-df-zA-Z0-9]*"; + unlink glob $Args::temp_dir . $Args::file_prefix . "_temp*"; + } + + + close $main::fh_out unless ( $main::fh_out =~ /STD/ ); + close $main::fh_verbose unless ( $main::fh_verbose =~ /STD/ ); + + + exit; # jump over Subs + +} # end package Clean ######################################################################## -# subs +# subs for using several times ######################################################################## +{ + package Subs; + use strict; -sub create_eps() { - if ($EpsMode eq 'ly2eps') { # `--ly2eps' - # `$ lilypond --ps -dbackend=eps -dgs-load-fonts + sub create_ly2eps { # `--ly2eps' default + my $prefix = $Read::file_numbered; # with dir change to temp dir + + # `$ lilypond --ps -dbackend=eps -dgs-load-fonts \ # output=file_without_extension file.ly' # extensions are added automatically - system 'lilypond', '--ps', '-dbackend=eps', '-dinclude-eps-fonts', - '-dgs-load-fonts', "--output=$FileNumbered", $FileLy - and die 'Program lilypond does not work.'; - - foreach (glob $FileNumbered . '-*' . '.eps') { - print '.PSPIC ' . $_ . "\n"; - } # end foreach *.eps - - } elsif ($EpsMode eq 'pdf2eps') { # `--pdf2eps' - # `$ lilypond --pdf --output=file_with_no_extension file.ly' - # Extension .pdf is added automatically - system "lilypond", "--pdf", "--output=$FileNumbered", $FileLy - and die 'Program lilypond does not work.'; + my $opts = '--ps -dbackend=eps -dinclude-eps-fonts -dgs-load-fonts ' . + "--output=$prefix $prefix"; + &Subs::run_lilypond("$opts"); + + chdir $Temp::Cwd or + die "Could not change to former directory `$Temp::Cwd': $!"; + + foreach ( glob $Args::temp_dir . $prefix . '-*' . '.eps' ) { + print $main::fh_out '.PSPIC ' . $_; + } # end foreach + } + + sub create_pdf2eps { # `--pdf2eps' + my $prefix = $Read::file_numbered; # with dir change to temp dir + + &Subs::run_lilypond("--pdf --output=$prefix $prefix"); + + my $file_pdf = $prefix . '.pdf'; + my $file_ps = $prefix . '.ps'; + + # pdf2ps in temp dir + my $temp_file = &Subs::next_temp_file; + print $main::fh_verbose "\n##### run of `pdf2ps'"; # `$ pdf2ps file.pdf file.ps' - system 'pdf2ps', $FileNumbered . '.pdf', $FileNumbered . '.ps' - and die 'Program pdf2ps does not work.'; + my $output = `pdf2ps $file_pdf $file_ps 2> $temp_file`; + die 'Program pdf2ps does not work.' if ( $? ); + &Subs::shell_handling ( $output, $temp_file ); + print $main::fh_verbose "##### end run of `pdf2ps'\n"; + + # ps2eps in temp dir + $temp_file = &Subs::next_temp_file; + print $main::fh_verbose "\n##### run of `ps2eps'"; # `$ ps2eps file.ps' - system 'ps2eps', $FileNumbered . '.ps' - and die 'Program ps2eps does not work.'; + $output = `ps2eps $file_ps 2> $temp_file`; + die 'Program ps2eps does not work.' if ( $? ); + &shell_handling ( $output, $temp_file ); + print $main::fh_verbose "##### end run of `ps2eps'\n"; + # change back to former dir + chdir $Temp::Cwd or + die "Could not change to former directory `$Temp::Cwd': $!"; + + # handling of .eps file + my $file_eps = $Args::temp_dir . $prefix . '.eps'; # print into groff output - print '.PSPIC ' . $FileNumbered . '.eps' . "\n"; + print $main::fh_out '.PSPIC ' . $file_eps; + } - } else { - die "Wrong eps mode: $EpsMode"; + sub dir_time { # time and microseconds for temporary directory name + my $res; + my ( $sec, $min, $hour, $day_of_month, $month, $year, + $weak_day, $day_of_year, $is_summer_time ) = + localtime( time() ); + + $year += 1900; + $month += 1; + $month = '0' . $month if ( $month < 10 ); + $day_of_month = '0' . $day_of_month if ( $day_of_month < 10 ); + $hour = '0' . $hour if ( $hour < 10 ); + $min = '0' . $min if ( $min < 10 ); + $sec = '0' . $sec if ( $sec < 10 ); + + $res = $year . '-' . $month . '-' . $day_of_month . '_'; + $res .= $hour . '-' . $min . '-' . $sec; + + (my $second, my $micro_second) = Time::HiRes::gettimeofday(); + $res .= '_' . $micro_second; + } # end sub dir_time(). time for temporary directory + + sub license { + &version; + print STDOUT $main::License; } -} # end sub create_eps() + sub make_dir { # make directory or check if exists + my $arg = shift; + $arg =~ s/^\s*(.*)\s*$/$1/; -sub dir_time() { # time and microseconds for temporary directory name - my $res; - my ( $sec, $min, $hour, $day_of_month, $month, $year, - $weak_day, $day_of_year, $is_summer_time ) = - localtime( time() ); + unless ( $arg =~ m<^/> ) { # starts not with `/', so it's not absolute + my $cwd = $Temp::Cwd; + chomp $cwd; - $year += 1900; - $month += 1; - $month = '0' . $month if ( $month < 10 ); - $day_of_month = '0' . $day_of_month if ( $day_of_month < 10 ); - $hour = '0' . $hour if ( $hour < 10 ); - $min = '0' . $min if ( $min < 10 ); - $sec = '0' . $sec if ( $sec < 10 ); + die "Could not create directory $arg because current working " . + "directory is not writable." unless ( -w $cwd ); - $res = $year . '-' . $month . '-' . $day_of_month . '_'; - $res .= $hour . '-' . $min . '-' . $sec; + $cwd =~ s(/*$)(/); - (my $second, my $micro_second) = Time::HiRes::gettimeofday(); - $res .= '_' . $micro_second; -} # end sub dir_time(). time for temporary directory + $arg = $cwd . $arg; + } + return main::FALSE unless ( $arg ); -sub get_prog_name { - my ($v, $d, $f) = File::Spec->splitpath($0); - return $f; -} + if ( -d $arg ) { # $arg is a directory + return main::FALSE unless ( -w $arg ); + } else { # $arg is not a directory + if ( -e $arg ) { # $arg exists + -w $arg && unlink $arg || + die "could not delete `" . $arg . "': $!"; + } # end of if, existing $arg + File::Path::make_path( $arg, {mask=>oct('0700')}) # `mkdir -P' + or die "Could not create directory `$arg': $!"; -sub license { - &version; - print $License; -} + } # end if, else: not a directory + return $arg; + } # end sub make_dir() + sub next_temp_file { + state $n = 0; + my $temp_file = $Args::temp_dir . $Args::file_prefix . '_temp_' . ++$n; + print $main::fh_verbose "next temporary file: `$temp_file'"; + return $temp_file; + } -sub make_dir() { # make directory or check if exists - my $arg = $_[0]; - $arg =~ s/^\s*(.*)\s*$/$1/; + sub run_lilypond { + # arg is the options collection for lilypond to run + # either from ly2eps or pdf2eps + my $opts = shift; + chomp $opts; - unless ( m<^/> ) { # starts not with `/', so it's not absolute - my $cwd = $Cwd; - chomp $cwd; + my $temp_file = &Subs::next_temp_file; + my $output = main::EMPTYSTRING; - die "Could not create directory $arg because current working " . - "directory is not writable." unless ( -w $cwd ); + # change to temp dir + chdir $Args::temp_dir or + die "Could not change to temporary directory `$Args::temp_dir': $!"; - $cwd =~ s(/*$)(/); + print $main::fh_verbose "\n##### run of `lilypond'"; + $output = `lilypond $opts 2>$temp_file`; + die "Program lilypond does not work: $?" if ( $? ); + chomp $output; + &Subs::shell_handling( $output, $temp_file ); + print $main::fh_verbose "##### end run of `lilypond'\n"; - $arg = $cwd . $arg; + # stay in temp dir } + sub shell_handling { + # Handle ``-shell-command output in a string (arg1). + # stderr goes to temporarty file $TempFile. + my $out_string = shift; + my $temp_file = shift; - return 0 unless ( $arg ); + chomp $out_string; - if ( -d $arg ) { # $arg is a directory - return 0 unless ( -w $arg ); - } else { # $arg is not a directory - if ( -e $arg ) { # $arg exists - -w $arg && unlink $arg || die "could not delete " . $arg . ": $!"; - } # end of if, existing $arg + open my $fh_string, "<", \ $out_string or + die "could not read the string `$out_string': $!"; + for ( <$fh_string> ) { + chomp; + print $main::fh_out $_; + } + close $fh_string; + + $temp_file && -f $temp_file && -r $temp_file || + die "shell_handling(): $temp_file is not a readable file."; + open my $fh_temp, "<", $temp_file or + die "shell_handling(): could not read temporary file $temp_file: $!"; + for ( <$fh_temp> ) { + chomp; + print $main::fh_verbose $_; + } + close $fh_temp; - File::Path::make_path( $arg, {mask=>oct('0700')}) # `mkdir -P' - or die "Could not create directory '$arg': $!"; + unlink $temp_file unless ( $Args::keep_files ); + } - } # end if, else: not a directory - return $arg; -} # end sub mike_dir() + sub usage { # for `--help' + my $p = $main::prog; + my $usage = +qq*$p: +Read a `roff' file or standard input and transform `lilypond' parts +(everything between `.lilypond start' and `.lilypond end') into +temporary `EPS'-files that can be read by groff using `.PSPIC'. +There is also a command `.lilypond include <file_name>' that can +include a complete `lilypond' file into the `groff' document. -sub usage { # for `--help' - my $usage = -' -groff_lilypond [options] [--] [filename ...] +# Breaking options: +$p -h|--help|--usage # usage +$p -v|--version # version information +$p --license # the license is GPL >= 3 -# breaking options: -groff_lilypond -h|--help # usage -groff_lilypond -v|--version # version information -groff_lilypond --license # the license is GPL >= 3 -Read a roff file or standard input and transform `lilypond' . "'" . -' parts -(everything between `.lilypond start' . "'" . -' and `.lilypond end' . "'" . ') into -temporary EPS-files that can be read by groff using `.PSPIC' . "'" . -'. There -is also a command (`.lilypond include file_name' . "'" . -') that can include a -complete lilypond file into the groff document. +# Normal options: +$p [options] [--] [filename ...] -There are 2 options for influencing the way how the EPS files for the -roff display are generated: ---pdf2eps `lilypond' . "'" . ' generates a pdf file which is transformed ---ly2eps `lilypond' . "'" . ' generates EPS files directly +There are 2 options for influencing the way how the `EPS' files for the +`roff' display are generated: +--ly2eps `lilypond' generates `EPS' files directly (default) +--pdf2eps `lilypond' generates a `PDF' file that is transformed --keep_files do not delete any temporary files -Options with an argument: ---file_prefix=... start for the names of temporary files ---temp_dir=... provide the directory for temporary files (is created). - Directories must start with `/' . "'" . -', this is done by the option. - -'; print $usage; - -} # end sub usage() - +-V|--Verbose|--verbose print much information to STDERR -sub version { # for `--version' - print $Prog . " version " . $Version . " of " . $LastUpdate . - " is part of GNU groff"; - if ( $GroffVersion ) { - print "\n version " . $GroffVersion . "\n"; +Options with an argument: +--file_prefix=... start for the names of temporary files +-o|--output=... sent output in the groff language into file ... +--temp_dir=... provide the directory for temporary files. + This is created if it does not exist. + +Perl >=5.10.0 needed.*; + print STDOUT $usage; + } # end sub usage() + + sub version { # for `--version' + my $end; + if ( $main::groff_version ) { + $end = " version $main::groff_version"; } else { - print ".\n"; + $end = '.'; } -} # end sub version() - - -# end subs + my $output = +qq*`$main::prog' version `$main::VERSION' of `$main::last_update' is part +of `GNU groff'$end*; -######################################################################## -# leaving file -######################################################################## + print STDOUT $output; + } # end sub version() -QUIT: +} # end package `Subs' ######################################################################## |