diff options
author | wl <wl> | 2013-08-11 08:30:04 +0000 |
---|---|---|
committer | wl <wl> | 2013-08-11 08:30:04 +0000 |
commit | 0d475003833d6e09eeadbd81b35c8525437b6c16 (patch) | |
tree | 9b266499d38678e5188002323a0032c1d91b20b2 /contrib | |
parent | dd226e578e7a8a0a13826c0039318e6ce7869141 (diff) | |
download | groff-0d475003833d6e09eeadbd81b35c8525437b6c16.tar.gz |
Revert accidental removal of previous files.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/glilypond/ChangeLog | 141 | ||||
-rw-r--r-- | contrib/glilypond/ChangeLog.0x | 103 | ||||
-rw-r--r-- | contrib/glilypond/Makefile.sub | 86 | ||||
-rw-r--r-- | contrib/glilypond/README.txt | 39 | ||||
-rw-r--r-- | contrib/glilypond/args.pl | 504 | ||||
-rw-r--r-- | contrib/glilypond/glilypond.man | 916 | ||||
-rwxr-xr-x | contrib/glilypond/glilypond.pl | 763 | ||||
-rw-r--r-- | contrib/glilypond/oop_fh.pl | 311 | ||||
-rw-r--r-- | contrib/glilypond/subs.pl | 469 |
9 files changed, 3332 insertions, 0 deletions
diff --git a/contrib/glilypond/ChangeLog b/contrib/glilypond/ChangeLog new file mode 100644 index 00000000..45eeaf2b --- /dev/null +++ b/contrib/glilypond/ChangeLog @@ -0,0 +1,141 @@ +2013-05-10 Bernd Warken <groff-bernd.warken-72@web.de> + + * glilypond.pl: Correct position information. Add debug code. + + * args.pl, oop_fh.pl, subs.pl: Correct position information. + +2013-04-25 Bernd Warken <groff-bernd.warken-72@web.de> + + * Makefile.sub: minor corrections. + +2013-04-24 Bernd Warken <groff-bernd.warken-72@web.de> + + Public `glilypond' version `v1.1'. + + * args.pl, sub.pl, glilypond.man: Change option `-v' to mean + `--verbose' instead of former `--version' such as many GNU + programs do. Correct sub `&usage()' and man-page. + + * args.pl, glilypond.pl, oop_fh.pl, subs.pl: Remove spaces in + ` -> ', some `( ... )', and some `{ ... }' places for better + readability of the Perl source code. + +2013-04-24 Bernd Warken <groff-bernd.warken-72@web.de> + + * args.pl, oop_fh.pl: Remove 1st line calling `perl'. + + * subs.pl: Remove 1st line calling `perl'. Remove sub + `&perl_version()'. Adjust sub `&usage()'. + + * glilypond.pl: Keep 1st line, which will be reset by running + `make'. Remove all parts of Perl testing. + + * perl_test.pl: Remove this file. + + * README.txt: Add information about needed Perl version. + + * Makefile.sub: Corrections for removing Perl test. Use `$<'. + +2013-04-24 Bernd Warken <groff-bernd.warken-72@web.de> + + * Makefile.sub: Remove Perl test. + +2013-04-12 Bernd Warken <groff-bernd.warken-72@web.de> + + * glilypond.pl: Fix END for early exit of `--version'. + +2013-04-12 Bernd Warken <groff-bernd.warken-72@web.de> + + * subs.pl: Replace `state' by global variable. So the Perl + version can be older. + + * perl_test.pl: Replace the Perl version by `v5.6', analogously to + `groffer'. + +2013-04-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * Makefile.sub: Corrections for Emacs. + +2013-04-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * old groff_lilypond: There is now a free `git' package containing + all old versions of the former name `groff_lilypond v0.*'. They + work with `lilypond' parts in `roff' files, but were not + installed. This package can be got at: + + $ git clone git@github.com:RUNOFF/groff_lilypond.git + + The new versions `glilypond 1.*' are not included there. + +2013-03-29 Bernd Warken <groff-bernd.warken-72@web.de> + + Published version is `v1.0'. + + Run `autoconf' again. + +2013-03-29 Bernd Warken <groff-bernd.warken-72@web.de> + + * <groff_src_dir>/m4/groff.m4, <groff_src_dir>/configure.ac: Add + libdir information for `glilypond'. + + * <groff_src_dir>/Makefile.in: Add + `<groff_src_dir>/contrib/glilypond'. + + Run `autoconf'. + + `glilypond' can now be installed to the system. + +2013-03-29 Bernd Warken <groff-bernd.warken-72@web.de> + + Rename `groff_lilypond' to `glilypond'. So remove the former + source directory `<groff_src_dir>/contrib/lilypond' and newly + install `<groff_src_dir>/contrib/glilypond', which now has many + files. The new version starts at `v1.0'. + + Version will now be v1.*. All former files of versions v0.* + vanished or were renamed. This is not yet an information about + publishing. + + * ChangeLog.0x: old `ChangeLog' file for the old `groff_lilypond' + versions v0.*. In the future, this file won't be changed any + more. + + * ChangeLog: New file. It is this file. It displays the history + of `glilypond' versions v1.* or later. + + * glilypond.pl: New main Perl file written from + `groff_lilypond.pl' in a totally different way. It is split now + into 4 Perl files. + + * args.pl: New Perl file. It handles the command line options for + a run of `glilypond.pl'. + + * oop_fh.pl: New Perl file. OOP handling of file handles. + + * perl_test.pl: Test whether the actual Perl program has a + suitable versions. For `Makefile.sub' and `glilypond.pl'. + + * subs.pl: New Perl file. Defines the global subs for + `glilypond.pl'. + + * Makefile.sub: Newly written `Makefile' for this subdirectory of + `groff'. `glilypond' should be able to be installed by `make' + with this file. + + * glilypond.man: Newly written man-page for `glilypond'. + + * README.txt: New file about the installation. + +######################################################################## + +Copyright 2013 + Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. + +Local Variables: +version-control: never +coding: utf-8 +End: diff --git a/contrib/glilypond/ChangeLog.0x b/contrib/glilypond/ChangeLog.0x new file mode 100644 index 00000000..56fb55d0 --- /dev/null +++ b/contrib/glilypond/ChangeLog.0x @@ -0,0 +1,103 @@ +2013-04-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * old groff_lilypond: There is now a free `git' package containing + all old versions of the former name `groff_lilypond v0.*'. They + work with `lilypond' parts in `roff' files, but were not + installed. This package can be got at: + + $ git clone git@github.com:RUNOFF/groff_lilypond.git + + The new versions `glilypond 1.*' are not included there. + +2013-03-28 Bernd Warken <groff-bernd.warken-72@web.de> + + Rename `groff_lilypond' to `glilypond' for *.pl and *.man files. + Split the single Perl script into several minor *.pl files. + Construct `Makefile.sub' in order to have installed `glilypond'. + Public versions will be v1.x. + Rename `ChangeLog' to `ChangeLog.0x' for the old versions of + `groff_lilypond' v0.*. New `ChangeLog' for the new versions + `glilypond' 1.*. + + * groff_lilypond.pl: Vanished. Renamed to `glilypond.pl'. + * groff_lilypond.man: Vanished. Renamed to `glilypond.man'. + * ChangeLog.0x: Moved from `ChangeLog'. It is this file. It + describes only the old `groff_lilypond' versions v0.*. See file + `ChangeLog' for the files of the new `glilypond' v1.*. + +2013-03-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * groff_lilypond.pl: Publishing groff_lilypond version v0.6. + New options: -e|--eps_dir, -l|--license, -k|--keep_files, + -p|--prefix=..., -t|--temp_dir=... + Install --eps_dir as directory for the useful EPS files. + * groff_lilypond.man: Include the new options. Add section + SEE ALSO. + +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 + regions. Within `groff' mode. it is still allowed. + * groff_lilypond.man: Update `.lilypond include'. + +2013-02-23 Bernd Warken <groff-bernd.warken-72@web.de> + + New version v0.4 of groff_lilypond. + * groff_lilypond_pl: Major rewrite. + New options: --file_prefix, --temp_dir, and --license. + * groff_lilypond.man: documents the new features. + +2013-02-16 Bernd Warken <groff-bernd.warken-72@web.de> + + * groff_lilypond.man: Minor corrections. + +2013-02-12 Bernd Warken <groff-bernd.warken-72@web.de> + + * groff_lilypond.pl: Add deletion of unused temporary files. + +2013-02-12 Bernd Warken <groff-bernd.warken-72@web.de> + + * contrib/lilypond: Version v0.3 for groff_lilypond + * groff_lilypond.pl: A new request was added for importing + lilypond files: + .lilypond include ... + The argument handling was improved. + +2013-02-11 Bernd Warken <groff-bernd.warken-72@web.de> + + * contrib/lilypond: Version v0.2 for groff_lilypond + * groff_lilypond.pl: Now there are 2 modes for generationg the EPS + files: --ly2eps (the default) and --pdf2eps (that's the old mode + from version v0.1 with pdf to ps to eps). With ly2eps mode, + lilypond generates the EPS files itself, for each page one EPS + file. + * groff_lilypond.man: Corresponding updated man-page + +2013-02-10 Bernd Warken <groff-bernd.warken-72@web.de> + + * contrib/lilypond: New files for adding lilypond parts into groff + files. These files will not yet be installed. + * groff_lilypond.pl: Program written in Perl, version v0.1 + * groff_lilypond.man: Corresponding man-page + +Copyright 2013 + Free Software Foundation, Inc. + +Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. + +Local Variables: +version-control: never +mode: change-log-mode +coding: utf-8 +End: diff --git a/contrib/glilypond/Makefile.sub b/contrib/glilypond/Makefile.sub new file mode 100644 index 00000000..85393590 --- /dev/null +++ b/contrib/glilypond/Makefile.sub @@ -0,0 +1,86 @@ +# Makefile.sub for `glilypond' (integration into the `groff' source tree) + +# File position: <groff-source>/contrib/lilypond/Makefile.sub + +# Copyright (C) 2013 +# Free Software Foundation, Inc. +# Written by Werner Lemberg <wl@gnu.org> and +# Bernd Warken <groff-bernd.warken-72@web.de>. + +# Last update: 25 Apr 2013 + +# This file is part of `glilypond' which is part of `groff'. + +# `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. + +# `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 this program. If not, see <http://www.gnu.org/licenses/>. + +######################################################################## + +MAN1=glilypond.n + +MOSTLYCLEANADD=glilypond $(MAN1) + +# not all make programs have $(RM) predefined. +RM=rm -f + +all: glilypond + + +# files going to lib directory `$(glilypond_dir)' + +GLILYPOND_LIB=$(srcdir)/subs.pl \ + $(srcdir)/oop_fh.pl \ + $(srcdir)/args.pl + +GLILYPOND_LIB_=`echo $(GLILYPOND_LIB) | sed 's|$(srcdir)/||g'` + + +# create perl executable `glilypond', being stored into `bindir' + +glilypond: $(srcdir)/glilypond.pl + sed -f "$(SH_DEPS_SED_SCRIPT)" \ + -e "s|@g@|$(g)|g" \ + -e "s|@BINDIR@|$(DESTDIR)$(bindir)|g" \ + -e "s|@glilypond_dir@|$(DESTDIR)$(glilypond_dir)|g" \ + -e "s|@VERSION@|$(version)$(revision)|g" \ + $(srcdir)/glilypond.pl >$@ + chmod +x $@ + + +install_data: glilypond $(GLILYPOND_LIB) + -test -d $(DESTDIR)$(bindir) \ + || $(mkinstalldirs) $(DESTDIR)$(bindir) + $(RM) $(DESTDIR)$(bindir)/$< + $(INSTALL_SCRIPT) glilypond $(DESTDIR)$(bindir)/$< + -test -d $(DESTDIR)$(glilypond_dir) \ + || $(mkinstalldirs) $(DESTDIR)$(glilypond_dir) + for f in $(GLILYPOND_); do \ + $(RM) $(DESTDIR)$(glilypond_dir)/$$f; \ + $(INSTALL_SCRIPT) $(srcdir)/$$f $(DESTDIR)$(glilypond_dir)/$$f; \ + done + + +uninstall_sub: + $(RM) $(DESTDIR)$(bindir)/glilypond; + for f in $(GLILYPOND_); do \ + $(RM) $(DESTDIR)$(glilypond_dir)/$$f; \ + done + -rmdir $(DESTDIR)$(glilypond_dir) + +######################################################################## +# Emacs settings +######################################################################## +# +# Local Variables: +# mode: makefile +# End: diff --git a/contrib/glilypond/README.txt b/contrib/glilypond/README.txt new file mode 100644 index 00000000..148dc139 --- /dev/null +++ b/contrib/glilypond/README.txt @@ -0,0 +1,39 @@ + Copyright (C) 2013 + Free Software Foundation, Inc. + + Written by Bernd Warken <groff-bernd.warken-72@web.de> + + Last update: 24 Apr 2013 + + Copying and distribution of this file, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. + + This file is part of `glilypond', which is part of `groff'. + + +######################################################################## + +In order to run `glilypond', your system must have installed Perl of at +least version `v5.6'. + + +######################################################################## + +In order to have this program installed by `make', the creation of a +libdir (library directory) must be programmed in some system files. +The following actions must be taken: + +1) <groff_src_dir>/m4/groff.m4: +Add `AC_DEFUN([GROFF_GROFFERDIR_DEFAULT])'. + +2) <groff_src_dir>/configure.ac: +Add `GROFF_GROFFERDIR_DEFAULT'. + +3) <groff_src_dir>/Makefile.in: +Add several informations of `glilypond_dir' + +With that, the program `autoconf' can be run in order to update the +configure files and Makefile's. + +Now `$glilypond_dir' can be used as libdir. diff --git a/contrib/glilypond/args.pl b/contrib/glilypond/args.pl new file mode 100644 index 00000000..1a007ba5 --- /dev/null +++ b/contrib/glilypond/args.pl @@ -0,0 +1,504 @@ +######################################################################## +# Legalese +######################################################################## + +my $License = q* +groff_lilypond - integrate `lilypond' into `groff' files + +Source file position: `<groff-source>/contrib/glilypond/args.pl' +Installed position: `<prefix>/lib/groff/glilypond' + +Copyright (C) 2013 Free Software Foundation, Inc. + Written by Bernd Warken <groff-bernd.warken-72@web.de> + +Last update: 10 May 2013 + +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 +option) any later version. + + `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/>. +*; + +##### end legalese + + +# use strict; +# use warnings; +# use diagnostics; + +use integer; + +our ( $Globals, $Args, $stderr, $v, $out ); + +# ---------- +# subs for second run, for remaining long options after splitting and +# transfer +# ---------- + +my %opts_with_arg = + ( + + '--eps_dir' => sub { + $Args->{'eps_dir'} = shift; + }, + + '--output' => sub { + $Args->{'output'} = shift; + }, + + '--prefix' => sub { + $Args->{'prefix'} = shift; + }, + + '--temp_dir' => sub { + $Args->{'temp_dir'} = shift; + }, + + ); # end of %opts_with_arg + + +my %opts_noarg = + ( + + '--help' => sub { + &usage; + exit; + }, + + '--keep_all' => sub { + $Args->{'keep_all'} = TRUE; + }, + + '--license' => sub { + &license; + exit; + }, + + '--ly2eps' => sub { + $Args->{'eps_func'} = 'ly'; + }, + + '--pdf2eps' => sub { + $Args->{'eps_func'} = 'pdf'; + }, + + '--verbose' => sub { + $Args->{'verbose'} = TRUE; + }, + + '--version' => sub { + &version; + exit; + }, + + ); # end of %opts_noarg + + +# used variables in both runs + +my @files = EMPTYARRAY; + + +#---------- +# first run for command line arguments +#---------- + +# global variables for first run + +my @splitted_args; +my $double_minus = FALSE; +my $arg = EMPTYSTRING; +my $has_arg = FALSE; + + +# Split short option collections and transfer these to suitable long +# options from above. Note that `-v' now means `--verbose' in version +# `v1.1', earlier versions had `--version' for `-v'. + +my %short_opts = + ( + '?' => '--help', + 'e' => '--eps_dir', + 'h' => '--help', + 'l' => '--license', + 'k' => '--keep_all', + 'o' => '--output', + 'p' => '--prefix', + 't' => '--temp_dir', + 'v' => '--verbose', + 'V' => '--verbose', + ); + + +# transfer long option abbreviations to the long options from above + +my @long_opts; + +$long_opts[3] = + { # option abbreviations of 3 characters + '--e' => '--eps_dir', + '--f' => '--prefix', # --f for --file_prefix + '--h' => '--help', + '--k' => '--keep_all', # and --keep_files + '--o' => '--output', + '--p' => '--prefix', # and --file_prefix + '--t' => '--temp_dir', + '--u' => '--help', # '--usage' is mapped to `--help' + }; + +$long_opts[4] = + { # option abbreviations of 4 characters + '--li' => '--license', + '--ly' => '--ly2eps', + '--pd' => '--pdf2eps', + '--pr' => '--prefix', + }; + +$long_opts[6] = + { # option abbreviations of 6 characters + '--verb' => '--verbose', + '--vers' => '--version', + }; + + +# subs for short splitting and replacing long abbreviations + +my $split_short = sub { + + my @chars = split //, $1; # omit leading dash + + # if result is TRUE: run `next SPLIT' afterwards + + CHARS: while ( @chars ) { + my $c = shift @chars; + + unless ( exists $short_opts{$c} ) { + $stderr->print( "Unknown short option `-$c'." ); + next CHARS; + } + + # short option exists + + # map or transfer to special long option from above + my $transopt = $short_opts{$c}; + + if ( exists $opts_noarg{$transopt} ) { + push @splitted_args, $transopt; + $Args->{'verbose'} = TRUE if ( $transopt eq '--verbose' ); + next CHARS; + } + + if ( exists $opts_with_arg{$transopt} ) { + push @splitted_args, $transopt; + + if ( @chars ) { + # if @chars is not empty, option $transopt has argument + # in this arg, the rest of characters in @chars + push @splitted_args, join "", @chars; + @chars = EMPTYARRAY; + return TRUE; # use `next SPLIT' afterwards + } + + # optarg is the next argument + $has_arg = $transopt; + return TRUE; # use `next SPLIT' afterwards + } # end of if %opts_with_arg + } # end of while CHARS + return FALSE; # do not do anything +}; # end of sub for short_opt_collection + + +my $split_long = sub { + my $from_arg = shift; + $from_arg =~ /^([^=]+)/; + my $opt_part = lc($1); + my $optarg = undef; + if ( $from_arg =~ /=(.*)$/ ) { + $optarg = $1; + } + + N: for my $n ( qw/6 4 3/ ) { + $opt_part =~ / # match $n characters + ^ + ( + .{$n} + ) + /x; + my $argn = $1; # get the first $n characters + + # no match, so luck for fewer number of chars + next N unless ( $argn ); + + next N unless ( exists $long_opts[$n]->{$argn} ); + # not in $n hash, so go on to next loop for $n + + # now $n-hash has arg + + # map or transfer to special long opt from above + my $transopt = $long_opts[$n]->{$argn}; + + # test on option without arg + if ( exists $opts_noarg{$transopt} ) { # opt has no arg + $stderr->print( 'Option ' . $transopt . 'has no argument: ' . + $from_arg . '.' ) if ( defined($optarg) ); + push @splitted_args, $transopt; + $Args->{'verbose'} = TRUE if ( $transopt eq '--verbose' ); + return TRUE; # use `next SPLIT' afterwards + } # end of if %opts_noarg + + # test on option with arg + if ( exists $opts_with_arg{$transopt} ) { # opt has arg + push @splitted_args, $transopt; + + # test on optarg in arg + if ( defined($optarg) ) { + push @splitted_args, $1; + return TRUE; # use `next SPLIT' afterwards + } # end of if optarg in arg + + # has optarg in next arg + $has_arg = $transopt; + return TRUE; # use `next SPLIT' afterwards + } # end of if %opts_with_arg + + # not with and without option, so is not permitted + $stderr->print( "`" . $transopt . + "' is unknown long option from `" . $from_arg . "'" ); + return TRUE; # use `next SPLIT' afterwards + } # end of for N + return FALSE; # do nothing +}; # end of split_long() + + +#---------- +# do split and transfer arguments +#---------- +sub run_first { + + SPLIT: foreach (@ARGV) { + # Transform long and short options into some given long options. + # Split long opts with arg into 2 args (no `='). + # Transform short option collections into given long options. + chomp; + + if ( $has_arg ) { + push @splitted_args, $_; + $has_arg = EMPTYSTRING; + next SPLIT; + } + + if ( $double_minus ) { + push @files, $_; + next SPLIT; + } + + if ( $_ eq '-' ) { # file arg `-' + push @files, $_; + next SPLIT; + } + + if ( $_ eq '--' ) { # POSIX arg `--' + push @splitted_args, $_; + $double_minus = TRUE; + next SPLIT; + } + + if ( / # short option or collection of short options + ^ + - + ( + [^-] + .* + ) + $ + /x ) { + $split_short->($1); + next SPLIT; + } # end of short option + + if ( /^--/ ) { # starts with 2 dashes, a long option + $split_long->($_); + next SPLIT; + } # end of long option + + # unknown option without leading dash is a file name + push @files, $_; + next SPLIT; + } # end of foreach SPLIT + + # all args are considered + $stderr->print( "Option `$has_arg' needs an argument." ) + if ( $has_arg ); + + + push @files, '-' unless ( @files ); + @ARGV = @splitted_args; + +}; # end of first run, splitting with map or transfer + + +#---------- +# open or ignore verbose output +#---------- +sub install_verbose { + if ( $Args->{'verbose'} ) { # `--verbose' was used + # make verbose output into $v + my $s = $v->get(); # get content of string so far as array ref, close + + $v = new FH_STDERR(); # make verbose output into STDERR + if ( $s ) { + for ( @$s ) { + # print the file content into new verbose output + $v->print($_); + } + } + # verbose output is now active (into STDERR) + $v->print( "Option `-v' means `--verbose'." ); + $v->print( "Version information is printed by option `--version'." ); + $v->print( "#" x 72 ); + + } else { # `--verbose' was not used + # do not be verbose, make verbose invisible + + $v->close(); # close and ignore the string content + + $v = new FH_NULL(); + # this is either into /dev/null or in an ignored string + + } # end if-else about verbose + # `$v->print' works now in any case + + $v->print( "Verbose output was chosen." ); + + my $s = $Globals->{'prog_is_installed'} ? '' : ' not'; + $v->print( $Globals->{'prog'} . " is" . $s . + " installed." ); + + $v->print( 'The command line options are:' ); + + $s = " options:"; + $s .= " `" . $_ . "'" for ( @ARGV ); + $v->print( $s ); + + $s = " file names:"; + $s .= " `" . $_ . "'\n" for ( @files ); + $v->print( $s ); +} # end install_verbose() + + +#---------- +# second run of command line arguments +#---------- +sub run_second { + # Second run of args with new @ARGV from the former splitting. + # Arguments are now splitted and transformed into special long options. + + my $double_minus = FALSE; + my $has_arg = FALSE; + + ARGS: for my $arg ( @ARGV ) { + + # ignore `--', file names are handled later on + last ARGS if ( $arg eq '--' ); + + if ( $has_arg ) { + unless ( exists $opts_with_arg{$has_arg} ) { + $stderr->print( "`\%opts_with_args' does not have key `" . + $has_arg . "'." ); + next ARGS; + } + + $opts_with_arg{$has_arg}->($arg); + $has_arg = FALSE; + next ARGS; + } # end of $has_arg + + if ( exists $opts_with_arg{$arg} ) { + $has_arg = $arg; + next ARGS; + } + + if ( exists $opts_noarg{$arg} ) { + $opts_noarg{$arg}->(); + next ARGS; + } + + # not a suitable option + $stderr->print( "Wrong option `" . $arg . "'." ); + next ARGS; + + } # end of for ARGS: + + + if ( $has_arg ) { # after last argument + die "Option `$has_arg' needs an argument."; + } + + }; # end of second run + + +sub handle_args { + # handling the output of args + + if ( $Args->{'output'} ) { # `--output' was set in the arguments + my $out_path = &path2abs($Args->{'output'}); + die "Output file name $Args->{'output'} cannot be used." + unless ( $out_path ); + + my ( $file, $dir ); + ( $file, $dir ) = File::Basename::fileparse($out_path) + or die "Could not handle output file path `" . $out_path . "': " . + "directory name `" . $dir . "' and file name `" . $file . "'."; + + die "Could not find output directory for `" . $Args->{'output'} . "'" + unless ( $dir ); + die "Could not find output file: `" . $Args->{'output'} . + "'" unless ( $file ); + + if ( -d $dir ) { + die "Could not write to output directory `" . $dir . "'." + unless ( -w $dir ); + } else { + $dir = &make_dir($dir); + die "Could not create output directory in: `" . $out_path . "'." + unless ( $dir ); + } + + # now $dir is a writable directory + + if ( -e $out_path ) { + die "Could not write to output file `" . $out_path . "'." + unless ( -w $out_path ); + } + + $out = new FH_FILE( $out_path ); + $v->print( "Output goes to file `" . $out_path . "'." ); + } else { # `--output' was not set + $out = new FH_STDOUT(); + } + # no $out is the right behavior for standard output + +# $Args->{'prefix'} .= '_' . $Args->{'eps_func'} . '2eps'; + + @ARGV = @files; +} + + +1; +######################################################################## +### Emacs settings +# Local Variables: +# mode: CPerl +# End: diff --git a/contrib/glilypond/glilypond.man b/contrib/glilypond/glilypond.man new file mode 100644 index 00000000..7e35019c --- /dev/null +++ b/contrib/glilypond/glilypond.man @@ -0,0 +1,916 @@ +.TH glilypond @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" +.SH NAME +glilypond \[em] integrate \f[CI]lilypond\f[P] parts into \f[CI]groff\f[] +. +.\" This .SH was moved to this place in order to appease `apropos'. +. +.\" -------------------------------------------------------------------- +.\" Legalese +.\" -------------------------------------------------------------------- +. +.de authors +This file was written by Bernd Warken +.MT groff\-bernd.warken\-72@web.de +.ME . +. +Last update: 25 Apr 2013 +.. +. +. +.\" The following macro .copying contains the license information for this file. +.de copying +.nh +.nf +glilypond - integrate lilypond into groff files + +Source file position: <groff-source>/contrib/lilypond/glilypond.man +Installed position: <prefix>/share/man/man1/glilypond.1 + +Copyright \(co 2013 + Free Software Foundation, Inc. + +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 option") any later version. + +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. + +.hy +.fi +If not, see the GNU licenses at +.UR http://www.gnu.org/licenses/ +.UE . +.. +. +. +.\" -------------------------------------------------------------------- +.\" Setup +.\" -------------------------------------------------------------------- +. +.ds Ellipsis "\&.\|.\|.\&\" +. +. +.\" -------------------------------------------------------------------- +.\" Macro definitions +.\" -------------------------------------------------------------------- +. +.\" -------------------------------------------------------------------- +.\" .FONT (<font name> <text> [<font name> <text> ...]) +.\" +.\" Print in different fonts: R, I, B, CR, CI, CB +.\" +.de1 FONT +. if (\\n[.$] = 0) \{\ +. nop \&\f[P]\& +. return +. \} +. ds result \& +. while (\\n[.$] >= 2) \{\ +. as result \,\f[\\$1]\\$2 +. if !"\\$1"P" .as result \f[P] +. shift 2 +. \} +. if (\\n[.$] = 1) .as result \,\f[\\$1] +. nh +. nop \\*[result]\& +. hy +.. +. +. +.\" -------------------------------------------------------------------- +.\" .OP+ (<option> [ [ | option] ...] [<optarg> [<end>] ]) +.\" +.\" like .OP, but with 1st arg split and and optional final character +.\" Example: `.OP+ -p | --prefix ly .' gets `[-t|--prefix ly].' +.\" Example: `.OP+ -h | --help | --usage' gets `[-h|--help|--usage]' +.\" Example: `.OP+ -v | --verbose "" ,' gets `[-v|--verbose],' +.\" +.de1 OP+ +. if ( \\n[.$] == 0 ) \{\ +. nop \&\f[CR][]\fR\& +. return +. \} +. nh +. ds result \&\f[CR][\f[CB]\\$1 +. shift +. while (\\n[.$] >= 2) \{\ +. ie '\\$1'|' .as result \f[CR]|\f[CB]\\$2 +. el \{\ +. ie '\\$1'' .as result \f[CR]]\fR\\$2 +. el .as result \fI\ \\$1\f[CR]]\fR\\$2 +. nop \\*[result]\& +. hy +. return +. \} +. shift 2 +. \} +. as result \fI\ \\$1\f[CR]]\fR +. nop \\*[result]\& +. hy +.. +. +.\" -------------------------------------------------------------------- +.SH "SYNOPSIS" +.\" -------------------------------------------------------------------- +. +.SY glilypond +.OP+ options +.OP+ - +.OP+ -- +.OP+ \%filespec \*[Ellipsis] +.YS +. +. +.\" -------------------------------------------------------------------- +.SH DESCRIPTION +.\" -------------------------------------------------------------------- +. +.FONT CB glilypond +transforms sheet music written in the +.FONT CI lilypond +language into the +.BR groff (@MAN7EXT@) +language using the +.FONT CB .PSPIC +request, such that +.BR groff (@MAN1EXT@) +can transform it into a format that can be displayed directly. +. +. +.P +Files in +.FONT CI groff +language and +.FONT CI "standard input" +can be provided as arguments. +. +. +.\" -------------------------------------------------------------------- +.SH "OPTION OVERVIEW" +.\" -------------------------------------------------------------------- +. +.\" -------------------------------------------------------------------- +.SS "Breaking Options" +.\" -------------------------------------------------------------------- +. +.SY +.OP+ -? | -h | --help | --usage +.YS +.SY +.OP+ --version +.YS +.SY +.OP+ -l | --license +.YS +. +. +.\" -------------------------------------------------------------------- +.SS "Options for building EPS Files" +.\" -------------------------------------------------------------------- +. +.TP +.OP+ --ly2eps +Here the +.FONT CB lilypond +program creates +.FONT CI eps +files directly. +. +This is the default. +. +. +.TP +.OP+ --pdf2eps +The program +.FONT CB glilypond +generates a +.FONT CI pdf +file using +.FONT CB lilypond R . +. +Then the +.FONT CI eps +file is generated by +.FONT CB pdf2ps +and +.FONT CB ps2eps R . +. +. +.\" -------------------------------------------------------------------- +.SS "Directories and Files" +.\" -------------------------------------------------------------------- +. +.TP +.OP+ -e | --eps_dir directory_name +Normally all +.FONT CI EPS +files are sent to the temporary directory. +. +With this option, you can generate your own directory, in which all useful +.FONT CI EPS +files are send. +. +So at last, the temporary directory can be removed. +. +. +.TP +.OP+ -p | --prefix begin_of_name +Normally all temporary files get names that start with the +.FONT CB ly CI \*[Ellipsis] +prefix. +. +With this option, you can freely change this prefix. +. +. +.TP +.OP+ -k | --keep_all +Normally all temporary files without the +.FONT CI eps +files are deleted. +. +With this opton, all generated files either by the +.FONT CB lilypond +program or other format transposers are kept. +. +. +.TP +.OP+ -t | --temp_dir dir +With this option, you call a directory that is the base for the +temporary directory. +. +This directory name is used as is without any extensions. +. +If this directory does not exist it is be created. +. +The temporary directory is created by Perl's security operations +directly under this directory. +. +In this temporary directory, the temporary files are stored. +. +. +.\" -------------------------------------------------------------------- +.SS "Output" +.\" -------------------------------------------------------------------- +. +.TP +.OP+ -o | --output file_name +Normally all +.FONT CI groff +output of this program is sent to +.FONT CB STDOUT R . +. +With this option, that can be changed, such that the output is stored +into a file named in the option argument +.IR file_name . +. +. +.TP +.OP+ -v | -V | --verbose +A lot more of information is sent to STDERR. +. +. +.\" -------------------------------------------------------------------- +.SS "Short Option Collections" +.\" -------------------------------------------------------------------- +. +The argument handling of options +. +. +.P +.FONT CI "Short options" +are arguments that start with a single dash +.FONT CB \- R . +. +Such an argument can consist of arbitrary many options without option +argument, composed as a collection of option characters following the +single dash. +. +. +.P +Such a collection can be terminated by an option character that +expects an option argument. +. +If this option character is not the last character of the argument, +the follwing final part of the argument is the option argument. +. +If it is the last character of the argument, the next argument is +taken as the option argument. +. +. +.P +This is the standard for +.FONT CI POSIX +and +.FONT CI GNU +option management. +. +. +.P +For example, +. +.TP +.FONT CB \-kVesome_dir +is a collection of the short options +.FONT CB \-k +and +.FONT CB \-V +without option argument, followed by the short option +.FONT CB \-e +with option argument that is the following part of the argument +.FONT CB some_dir R . +. +So this argument could also be written as several arguments +.FONT CB "\-k \-V \-e some_dir" R . +. +. +.\" -------------------------------------------------------------------- +.SS "Handling of Long Options" +.\" -------------------------------------------------------------------- +. +Arguments that start with a double dash +.FONT CB \-\- +are so-called +.FONT CI "long options" R . +. +Each double dash argument can only have a single long option. +. +. +.P +.FONT CI "Long options" +have or have not an option argument. +. +An option argument can be the next argument or can be appended with an +equal sign +.FONT CB = +to the same argument as the long option. +. +. +.TP +.FONT CB \-\-help +is a long option without an option argument. +. +.TP +.FONT CB "\-\-eps_dir some_dir" +.TQ +.FONT CB "\-\-eps_dir=some_dir" +is the long option +.FONT CB "\-\-eps_dir +with the option argument +.FONT CB some_dir R . +. +. +.P +Moreover the program allows abbreviations of long options, as much as +possible. +. +. +.P +The +.FONT CI "long option" +.FONT CB \-\-keep_all +can be abbreviated from +.FONT CB \-\-keep_al +up to +.FONT CB \-\-k +because the program does not have another +.FONT CI "long option" +whose name starts with the character +.FONT CB k R . +. +. +.P +On the other hand, the option +.FONT CB \-\-version +cannot be abbreviated further than +.FONT CB \-\-vers +because there is also the +.FONT CI "long option " CB \-\-verbose +that can be abbreviated up to +.FONT CB \-\-verb R . +. +. +.P +An option argument can also be appended to an abbreviation. +. +So is +.FONT CB \-\-e=some_dir +the same as +.FONT CB "\-\-eps_dir some_dir" R . +. +. +.P +Moreover the program allows an arbitrary usage of upper and lower case +in the option name. +. +This is +.FONT CI Perl +style. +. +. +.P +For example, the +.FONT CI "long option" +.FONT CB \-\-keep_all +can as well be written as +.FONT CB \-\-Keep_All +or even as an abbreviation like +.FONT CB \-\-KeE R . +. +. +.\" -------------------------------------------------------------------- +.SH FILESPEC ARGUMENTS +.\" -------------------------------------------------------------------- +. +An argument that is not an option or an option argument is called a +.FONT CI filespec +argument. +. +. +.P +Without any +.I filespec +argument, +.FONT CI "standard input" +is read. +. +. +.P +Each +.I filespec +argument must either be the name of a readable file or a dash +.FONT CB - +for +.FONT CI "standard input" R . +. +Each input must be written in the +.FONT CI roff +or +.FONT CI groff +language and can include +.FONT CI lilypond +parts. +. +. +.P +Normally arguments starting with a dash +.FONT CB \- +are interpreted as an option. +. +But if you use an argument that consists only of a doubled dash +.FONT CB \-\- R , +all following arguments are taken as +.FONT CI filespec +argument, even if such an argument starts with a dash. +. +This is handled according to the +.FONT CI GNU +standard. +. +. +.\" -------------------------------------------------------------------- +.SH "THE LILYPOND PARTS IN ROFF INPUT" +.\" -------------------------------------------------------------------- +. +.\" -------------------------------------------------------------------- +.SS "Integrated Lilypond Codes" +.\" -------------------------------------------------------------------- +. +A +.FONT CI lilypond +part within a structure written in the +.FONT CI groff +language is the whole part between the marks +.EX +.FONT CB ".lilypond start" +.EE +and +.EX +.FONT CB ".lilypond end" +.EE +. +. +.P +A +.FONT CI groff +input can have several of these +.FONT CI lilypond +parts. +. +. +.P +When processing such a +.FONT CI lilypond +part between +.FONT CB ".lilypond start" +and +.FONT CB ".lilypond end" +we say that the +.FONT CB glilypond +program is in +.FONT CI "lilypond mode" R . +. +. +.P +These +.FONT CI lilypond +parts are sent into temporary +.FONT CI lilypond +files with the file name extension +.FONT CB .ly R . +. +These files are transformed later on into +.FONT CI EPS +files. +. +. +.\" -------------------------------------------------------------------- +.SS "Inclusion of ly-Files" +.\" -------------------------------------------------------------------- +. +An additional command line for file inclusion of +.FONT CI lilypond +files is given by +.EX +.FONT CB ".lilypond include" I " file_name" +.EE +in +.FONT CI groff +input. +. +For each such +.FONT CI include +command, one file of +.FONT CI lilypond +code can be included into the +.FONT CI groff +code. +. +Arbitrarily many of these commands can be included in the +.FONT CI groff +input. +. +. +.P +These include commands can only be used outside the +.FONT CI lilypond +parts. +. +Within the +.FONT CI "lilypond mode" R , +this inclusion is not possible. +. +So +.FONT CB ".lilypond include" +may not be used in +.FONT CI "lilypond mode" R , +i.e. between +.FONT CB ".lilypond start" +and +.FONT CB ".lilypond end" R . +. +. +These included +.FONT CI ly R -files +are also transformed into +.FONT CI EPS +files. +. +. +.\" -------------------------------------------------------------------- +.SH "GENERATED FILES" +.\" -------------------------------------------------------------------- +. +By the transformation process of +.FONT CI lilypond +parts into +.FONT CI EPS +files, there are many files generated. +. +By default, these files are regarded as temporary files and as such +stored in a temporary directory. +. +. +.P +This process can be changed by command line options. +. +. +.\" -------------------------------------------------------------------- +.SS "Command Line Options for Directories" +.\" -------------------------------------------------------------------- +. +The temporary directory for this program is either created +automatically or can be named by the option +.OP+ -t | --temp_dir dir . +. +. +.P +Moreover, the +.FONT CI EPS +files that are later on referred by +.FONT CB .PSPIC +command in the final +.FONT CI groff +output can be stored in a different directory that can be set by the +command line option +.OP+ -e | --eps_dir directory_name . +. +With this option, the temporary directory can be removed completely at +the end of the program. +. +. +.P +The beginning of the names of the temporary files can be set by the +command line option +.OP+ -p | --prefix begin_of_name . +. +. +.P +All of the temporary files except the +.FONT CI EPS +files are deleted finally. +. +This can be changed by setting the command line option +.OP+ -k | --keep_files +. +With this, all temporary files and directories are kept, not deleted. +. +. +.P +These +.FONT CI EPS +files are stored in a temporary or +.FONT CI EPS +directory. +. +But they cannot be deleted by the transformation process because they +are needed for the display which can take a long time. +. +. +.\" -------------------------------------------------------------------- +.SH "TRANSFORMATION PROCESSES FOR GENERATING EPS FILES" +.\" -------------------------------------------------------------------- +. +.\" -------------------------------------------------------------------- +.SS "Mode ly2eps" +.\" -------------------------------------------------------------------- +. +This mode is the default. +. +It can also be chosen by the option +.FONT CB --ly2eps R . +. +. +.P +In this mode, the +.FONT CB .ly +files are transformed by the +.FONT CB lilypond +program into many files of different formats, including +.FONT CI eps +files, using +.EX +.FONT CB "$ lilypond \-\-ps \-dbackend=eps \-dgs\-load\-fonts \-\-output=" I file\-name +.EE +for each +.FONT CB .ly +file. +. +The output +.I file\-name +must be provided without an extension, its directory is temporary.. +. +. +.P +There are many +.FONT CI EPS +files created. +. +One having the complete transformed +.FONT CB ly +file, named +.FONT I file\-name CB .eps R . +. +. +.P +Moreover there are +.FONT CI EPS +files for each page, named +.FONT I file\-name CB \- I digit CB .eps R . +. +. +.P +The last step to be done is replacing all +.FONT CI lilypond +parts by the collection of the corresponding +.FONT CI EPS +page files. +. +This is done by +.FONT CI groff +commands +.EX +.FONT CB ".PSPIC " CI file-name CB \- I digit CB .eps +.EE +. +. +.\" -------------------------------------------------------------------- +.SS "Mode pdf2eps" +.\" -------------------------------------------------------------------- +. +This mode can be chosen by the option +.FONT CB --pdf2eps R . +. +. +.P +In this mode, the +.FONT CB .ly +files are transformed by the +.BR lilypond (1) +program into +.FONT CI pdf +files, using +.EX +.FONT CB "lilypond \-\-pdf \-\-output=" I file-name +.EE +for each +.FONT CB .ly +file. +. +The +.I file-name +must be provided without the extension +.FONT CB .pdf R . +. +By this process, a file +.FONT CI file-name CB .pdf +is generated. +. +. +.P +The next step is to transform these +.FONT CI PDF +files into a +.FONT CI PS +file. +. +This is done by the +.BR pdf2ps (1) +program using +.EX +.FONT R "$ " CB "pdf2ps " CI file-name CB ".pdf " CI file-name CB ".ps" +.EE +. +. +The next step creates an +.FONT CI EPS +file from the +.FONT CI PS +file. +. +This is done by the +.BR ps2eps (1) +program using +.EX +.FONT R "$ " CB "ps2eps " CI file-name CB ".ps" +.EE +. +. +.P +By that, a file +.FONT CI file-name CB .eps +is created for each +.FONT CI lilypond +part in the +.FONT CI groff +file or standard input. +. +. +.P +The last step to be done is replacing all +.FONT CI lilypond +parts by the +.FONT CI groff +command +.EX +.FONT CB ".PSPIC " CI file-name CB .eps +.EE +. +. +.\" -------------------------------------------------------------------- +.SH "THE GENERATED NEW ROFF STRUCTURE" +.\" -------------------------------------------------------------------- +. +The new +.BR groff (@MAN7EXT@) +structure generated by +.FONT CB glilypond +is either +. +.TP +1) +sent to standard output and can there be saved into a file or piped into +.BR groff (@MAN1EXT@) +or +.BR groffer (@MAN1EXT@) +or +. +.TP +2) +stored into a file by given the option +.OP -o\fR|\fB\~--output file_name +. +. +.\" -------------------------------------------------------------------- +.SH "SEE ALSO" +.\" -------------------------------------------------------------------- +. +.TP +.BR groff (@MAN1EXT@) +the usage of the groff program and pointers to the documentation and +availability of the +.FONT CI groff +system. +. +The main source of information for the +.FONT CI groff +szstem is the +.FONT CB groff +.BR info (1) +file. +. +. +.TP +.BR groff (@MAN7EXT@) +documents the +.FONT CI groff +language. +. +. +.TP +.BR groff_tmac (@MAN5EXT@) +contains documentation of the +.FONT CB .PSPIC +request. +. +. +.TP +.BR lilypond (1) +The documentation of the +.FONT CB lilypond +program. +. +The main source of information for the +.FONT CI lilypond +language is the +.FONT CB lilypond +.BR info (1) +file. +. +. +.TP +.BR pdf2ps (1) +transform a +.FONT CI PDF +file into a +.FONT CI Postscript +format. +. +. +.TP +.BR ps2eps (1) +transform a +.FONT CI PS +file into an +.FONT CI EPS +format. +. +. +.\" -------------------------------------------------------------------- +.SH "AUTHORS" +.\" -------------------------------------------------------------------- +.authors +. +. +.\" -------------------------------------------------------------------- +.SH "COPYING" +.\" -------------------------------------------------------------------- +.copying +. +. +.\" -------------------------------------------------------------------- +.\" Emacs settings +.\" -------------------------------------------------------------------- +. +.\" Local Variables: +.\" mode: nroff +.\" End: diff --git a/contrib/glilypond/glilypond.pl b/contrib/glilypond/glilypond.pl new file mode 100755 index 00000000..a40c8d64 --- /dev/null +++ b/contrib/glilypond/glilypond.pl @@ -0,0 +1,763 @@ +#! /usr/bin/env perl + +package main; + +######################################################################## +# debugging +######################################################################## + +# See `Mastering Perl', chapter 4. + +# use strict; +# use warnings; +# use diagnostics; + +use Carp; +$SIG[__DIE__] = sub { &Carp::croak; }; + +use Data::Dumper; + +######################################################################## +# Legalese +######################################################################## + +our $Legalese; + +{ + use constant VERSION => 'v1.1'; # version of glilypond + use constant LASTUPDATE => '10 May 2013'; # date of last update + +### This constant `LICENSE' is the license for this file `GPL' >= 3 + use constant LICENSE => q* +glilypond - integrate `lilypond' into `groff' files + +Source file position: `<groff-source>/contrib/glilypond/glilypond.pl' +Installed position: `<prefix>/bin/glilypond' + +Copyright (C) 2013 Free Software Foundation, Inc. + Written by Bernd Warken <groff-bernd.warken-72@web.de> + +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 +option) any later version. + + `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/>. +*; + + + $Legalese = + { + 'version' => VERSION, + 'last_update' => LASTUPDATE, + 'license' => LICENSE, + } + +} + +##### end legalese + + +######################################################################## +# global variables and BEGIN +######################################################################## + +use integer; +use utf8; + +use Cwd qw[]; +use File::Basename qw[]; +use File::Copy qw[]; +use File::HomeDir qw[]; +use File::Spec qw[]; +use File::Path qw[]; +use File::Temp qw[]; +use FindBin qw[]; +use POSIX qw[]; + + +BEGIN { + + use constant FALSE => 0; + use constant TRUE => 1; + use constant EMPTYSTRING => ''; + use constant EMPTYARRAY => (); + use constant EMPTYHASH => (); + + our $Globals = + { + 'before_make' => FALSE, + 'groff_version' => EMPTYSTRING, + 'prog' => EMPTYSTRING, + }; + + { + ( my $volume, my $directory, $Globals->{'prog'} ) = + File::Spec->splitpath($0); + # $Globals->{'prog'} is `glilypond' when installed, + # `glilypond.pl' when not + } + + + $\ = "\n"; # adds newline at each print + $/ = "\n"; # newline separates input + $| = 1; # flush after each print or write command + + + { + { + # script before run of `make' + my $at = '@'; + $Globals->{'before_make'} = TRUE if '@VERSION@' eq "${at}VERSION${at}"; + } + + my $file_test_pl; + my $glilypond_libdir; + + if ( $Globals->{'before_make'} ) { # in source, not yet installed + my $glilypond_dir = $FindBin::Bin; + $glilypond_dir = Cwd::realpath($glilypond_dir); + $glilypond_libdir = $glilypond_dir; + + } else { # already installed + $Globals->{'groff_version'} = '@VERSION@'; + $glilypond_libdir = '@glilypond_dir@'; + } + + unshift(@INC, $glilypond_libdir); + + umask 0077; # octal output: `printf "%03o", umask;' + } + + require 'subs.pl'; +} + +die "test: "; +######################################################################## +# OOP declarations for some file handles +######################################################################## + +require 'oop_fh.pl'; + +our $stdout = new FH_STDOUT(); +our $stderr = new FH_STDERR(); + +# verbose printing, not clear wether this will be set by `--verbose', +# so store this now into a string, which can be gotten later on, when +# it will become either STDERR or /dev/null +our $v = new FH_STRING(); + +# for standard output, either STDOUT or output file +our $out; + +# end of FH + + +######################################################################## +# Args: command line arguments +######################################################################## + +# command line arguments are handled in 2 runs: +# 1) split short option collections, `=' optargs, and transfer abbrevs +# 2) handle the transferred options with subs + +our $Args = + { + 'eps_dir' => EMPTYSTRING, # can be overwritten by `--eps_dir' + + # `eps-func' has 2 possible values: + # 1) `ly' from `--ly2eps' (default) + # 2) `pdf' `--pdf2eps' + 'eps_func' => 'ly', + + # files names of temporary files start with this string, + # can be overwritten by `--prefix' + 'prefix' => 'ly', + + # delete or do not delete temporary files + 'keep_all' => FALSE, + + # the roff output goes normally to STDOUT, can be a file with `--output' + 'output' => EMPTYSTRING, + + # temporary directory, can be overwritten by `--temp_dir', + # empty for default of the program + 'temp_dir' => EMPTYSTRING, + + # regulates verbose output (on STDERR), overwritten by `--verbose' + 'verbose' => FALSE, + }; + +{ # `Args' + require 'args.pl'; + &run_first(); + &install_verbose(); + &run_second(); + &handle_args(); +} + +# end `Args' + + +######################################################################## +# temporary directory .../tmp/groff/USER/lilypond/TIME +######################################################################## + +our $Temp = + { + # store the current directory + 'cwd' => Cwd::getcwd(), + + # directory for EPS files + 'eps_dir' => EMPTYSTRING, + + # temporary directory + 'temp_dir' => EMPTYSTRING, + }; + +{ # `Temp' + + if ( $Args->{'temp_dir'} ) { + + #---------- + # temporary directory was set by `--temp_dir' + #---------- + + my $dir = $Args->{'temp_dir'}; + + $dir = &path2abs($dir); + $dir = &make_dir($dir) or + die "The directory `$dir' cannot be used temporarily: $!"; + + + # now `$dir' is a writable directory + + opendir( my $dh, $dir ) or + die "Could not open temporary directory `$dir': $!"; + my $file_name; + my $found = FALSE; + my $prefix = $Args->{'prefix'}; + my $re = qr< + ^ + $prefix + _ + >x; + + READDIR: while ( defined($file_name = readdir($dh)) ) { + chomp $file_name; + if ( $file_name =~ /$re/ ) { # file name starts with $prefix_ + $found = TRUE; + last READDIR; + } + next; + } + + $Temp->{'temp_dir'} = $dir; + my $n = 0; + while ( $found ) { + $dir = File::Spec->catdir( $Temp->{'temp_dir'}, ++$n ); + next if ( -e $dir ); + + $dir = &make_dir($dir) or next; + + $found = FALSE; + last; + } + + $Temp->{'temp_dir'} = $dir; + + + } else { # $Args->{'temp_dir'} not given by `--temp_dir' + + #---------- + # temporary directory was not set + #---------- + + { # search for or create a temporary directory + + my @tempdirs = EMPTYARRAY; + { + my $tmpdir = File::Spec->tmpdir(); + push @tempdirs, $tmpdir if ( $tmpdir && -d $tmpdir && -w $tmpdir ); + + my $root_dir = File::Spec->rootdir(); # `/' in Unix + my $root_tmp = File::Spec->catdir($root_dir, 'tmp'); + push @tempdirs, $root_tmp + if ( $root_tmp ne $tmpdir && -d $root_tmp && -w $root_tmp ); + + # home directory of the actual user + my $home = File::HomeDir->my_home; + my $home_tmp = File::Spec->catdir($home, 'tmp'); + push @tempdirs, $home_tmp if ( -d $home_tmp && -w $home_tmp ); + + # `/var/tmp' in Unix + my $var_tmp = File::Spec->catdir('', 'var', 'tmp'); + push @tempdirs, $var_tmp if ( -d $var_tmp && -w $var_tmp ); + } + + + my @path_extension = qw( groff ); # TEMPDIR/groff/USER/lilypond/<NUMBER> + { + # `$<' is UID of actual user, + # `getpwuid' gets user name in scalar context + my $user = getpwuid($<); + push @path_extension, $user if ( $user ); + + push @path_extension, qw( lilypond ); + } + + + TEMPS: foreach ( @tempdirs ) { + + my $dir; # final directory name in `while' loop + $dir = &path2abs($_); + next TEMPS unless ( $dir ); + + # beginning of directory name + my @dir_begin = + ( File::Spec->splitdir($dir), @path_extension ); + + + my $n = 0; + my $dir_blocked = TRUE; + BLOCK: while ( $dir_blocked ) { + # should become the final dir name + $dir = File::Spec->catdir(@dir_begin, ++$n); + next BLOCK if ( -d $dir ); + + # dir name is now free, create it, and end the blocking + my $res = &make_dir( $dir ); + die "Could not create directory: $dir" unless ( $res ); + + $dir = $res; + $dir_blocked = FALSE; + } + + next TEMPS unless ( -d $dir && -w $dir ); + + # $dir is now a writable directory + $Temp->{'temp_dir'} = $dir; # tmp/groff/USER/lilypond/TIME + last TEMPS; + } # end foreach tmp directories + } # end to create a temporary directory + + die "Could not find a temporary directory" unless + ( $Temp->{'temp_dir'} && -d $Temp->{'temp_dir'} && + -w $Temp->{'temp_dir'} ); + + } # end temporary directory + + $v->print( "Temporary directory: `" . $Temp->{'temp_dir'} . "'\n" ); + $v->print( "file_prefix: `" . $Args->{'prefix'} . "'" ); + + + #---------- + # EPS directory + #---------- + + my $make_dir = FALSE; + if ( $Args->{'eps_dir'} ) { # set by `--eps_dir' + my $dir = $Args->{'eps_dir'}; + + $dir = &path2abs($dir); + + if ( -e $dir ) { + goto EMPTY unless ( -w $dir ); + + # `$dir' is writable + if ( -d $dir ) { + my $upper_dir = $dir; + + my $found = FALSE; + opendir( my $dh, $upper_dir ) or $found = TRUE; + my $prefix = $Args->{'prefix'}; + my $re = qr< + ^ + $prefix + _ + >x; + while ( not $found ) { + my $file_name = readdir($dh); + if ( $file_name =~ /$re/ ) { # file name starts with $prefix_ + $found = TRUE; + last; + } + next; + } + + my $n = 0; + while ( $found ) { + $dir = File::Spec->catdir($upper_dir, ++$n); + next if ( -d $dir ); + $found = FALSE; + } + $make_dir = TRUE; + $Temp->{'eps_dir'} = $dir; + } else { # `$dir' is not a dir, so unlink it to create it as dir + if ( unlink $dir ) { # could remove `$dir' + $Temp->{'eps_dir'} = $dir; + $make_dir = TRUE; + } else { # could not remove + stderr->print( "Could not use EPS dir `" . $dir . + "', use temp dir." ); + } # end of unlink + } # end test of -d $dir + } else { + $make_dir = TRUE; + } # end of if -e $dir + + + if ( $make_dir ) { # make directory `$dir' + my $made = FALSE; + $dir = &make_dir($dir) and $made = TRUE; + + if ( $made ) { + $Temp->{'eps_dir'} = $dir; + $v->print( "Directory for useful EPS files is `" . $dir . "'." ); + } else { + $v->print( "The EPS directory `" . $dir . "' cannot be used: $!" ); + } + } else { # `--eps_dir' was not set, so take the temporary directory + $Temp->{'eps_dir'} = $Args->{'temp_dir'}; + } # end of make dir + } + + EMPTY: unless ( $Temp->{'eps_dir'} ) { + # EPS-dir not set or available, use temp dir, + # but leave $Temp->{'}eps_dir'} empty + $v->print( "Directory for useful EPS files is the " . + "temporary directory `" . $Temp->{'temp_dir'} . "'." ); + } + +} # end `Temp' + + +######################################################################## +# Read: read files or stdin +######################################################################## + +our $Read = + { + 'file_numbered' => EMPTYSTRING, + 'file_ly' => EMPTYSTRING, # `$file_numbered.ly' + }; + +{ # read files or stdin + + my $ly_number = 0; # number of lilypond file + + # `$Args->{'prefix'}_[0-9]' + + my $lilypond_mode = FALSE; + + my $arg1; # first argument for `.lilypond' + my $arg2; # argument for `.lilypond include' + + my $path_ly; # path of ly-file + + + my $check_file = sub { # for argument of `.lilypond include' + my $file = shift; # argument is a file name + $file = &path2abs($file); + 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 $file; + }; # end sub &$check_file() + + + my $increase_ly_number = sub { + ++$ly_number; + $Read->{'file_numbered'} = $Args->{'prefix'} . '_' . $ly_number; + $Read->{'file_ly'} = $Read->{'file_numbered'} . '.ly'; + $path_ly = File::Spec->catdir($Temp->{'temp_dir'}, $Read->{'file_ly'} ); + }; + + + my %eps_subs = + ( + 'ly' => \&create_ly2eps, # lilypond creates EPS files + 'pdf' => \&create_pdf2eps, # lilypond creates PDF file + ); + + # about lines starting with `.lilypond' + + my $ly; + my $fh_include_file; + my %lilypond_args = + ( + + 'start' => sub { + $v->print( "\nline: `.lilypond start'" ); + die "Line `.lilypond stop' expected." if ( $lilypond_mode ); + + $lilypond_mode = TRUE; + &$increase_ly_number; + + $v->print( "ly-file: `" . $path_ly . "'" ); + + $ly = new FH_FILE($path_ly); + }, + + + 'end' => sub { + $v->print( "line: `.lilypond end'\n" ); + die "Expected line `.lilypond start'." unless ( $lilypond_mode ); + + $lilypond_mode = FALSE; + $ly->close(); + + if ( exists $eps_subs{ $Args->{'eps_func'} } ) { + $eps_subs{ $Args->{'eps_func'} }->(); + } else { + die "Wrong argument for \%eps_subs: " . $Args->{'eps_func'} . "'"; + } + }, + + + '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; + + $ly = new FH_FILE($path_ly); + + my $include = new FH_READ_FILE($file); + my $res = $include->read-all(); # is a refernce to an array + foreach ( @$res ) { + chomp; + $ly->print($_); + } + $ly->close(); + + if ( exists $eps_subs{ $Args->{'eps_func'} } ) { + $eps_subs{ $Args->{'eps_func'} }->(); + } else { + die "Wrong argument for \$eps_subs: `" . $Args->{'eps_func'} . "'"; + } + }, # end `.lilypond include' + + ); # end definition %lilypond_args + + + LILYPOND: foreach (<>) { + chomp; + my $line = $_; + + + # now the lines with '.lilypond ...' + + if ( / + ^ + [.'] + \s* + lilypond + ( + .* + ) + $ + /x ) { # .lilypond ... + my $args = $1; + $args =~ s/ + ^ + \s* + //x; + $args =~ s/ + \s* + $ + //x; + $args =~ s/ + ^ + ( + \S* + ) + \s* + //x; + 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}->($arg2); + next; + } else { + # not a suitable argument of `.lilypond' + $stderr->print( "Unknown command: `$arg1' `$arg2': `$line'" ); + } + + next LILYPOND; + } # end if for .lilypond + + + if ( $lilypond_mode ) { # do lilypond-mode + # see `.lilypond start' + $ly->print( $line ); + next LILYPOND; + } # do lilypond-mode + + # unknown line without lilypond + unless ( / + ^ + [.'] + \s* + lilypond + /x ) { # not a `.lilypond' line + $out->print($line); + next LILYPOND; + } + + } # end foreach <> +} # end Read + + +######################################################################## +# clean up +######################################################################## + +END { + + exit unless ( defined($Temp->{'temp_dir'}) ); + + if ( $Args->{'keep_all'} ) { + # With --keep_all, no temporary files are removed. + $v->print( "keep_all: `TRUE'" ); + $v->print( "No temporary files will be deleted:" ); + + opendir my $dh_temp, $Temp->{'temp_dir'} or + die "Cannot open " . $Temp->{'temp_dir'} . ": $!"; + for ( sort readdir $dh_temp ) { + next if ( / # omit files starting with a dot + ^ + \. + /x ); + if ( / + ^ + $Args->{'prefix'} + _ + /x ) { + my $file = File::Spec->catfile( $Temp->{'temp_dir'}, $_ ); + $v->print( "- " . $file ); + next; + } + next; + } # end for sort readdir + closedir $dh_temp; + + } else { # keep_all is not set + # Remove all temporary files except the eps files. + + $v->print( "keep_all: `FALSE'" ); + $v->print( "All temporary files except *.eps will be deleted" ); + + + if ( $Temp->{'eps_dir'} ) { + # EPS files are in another dir, remove temp dir + + if ( &is_subdir( $Temp->{'eps_dir'}, $Temp->{'temp_dir'} ) ) { + $v->print( "EPS dir is subdir of temp dir, so keep both." ); + } else { # remove temp dir + $v->print( "Try to remove temporary directory `" . + $Temp->{'temp_dir'} ."':" ); + if ( File::Path::remove_tree($Temp->{'temp_dir'}) ) { + # remove succeeds + $v->print( "...done." ); + } else { # did not remove + $v->print( "Failure to remove temporary directory." ); + } # end test on remove + } # end is subdir + + } else { # no EPS dir, so keep EPS files + + opendir my $dh_temp, $Temp->{'temp_dir'} or + die "Cannot open " . $Temp->{'temp_dir'} . ": $!"; + for ( sort readdir $dh_temp ) { + next if ( / # omit files starting with a dot + ^ + \. + /x ); + next if ( / # omit EPS-files + \.eps + $ + /x ); + if ( / + ^ + $Args->{'prefix'} + _ + /x ) { # this includes `PREFIX_temp*' + my $file = File::Spec->catfile( $Temp->{'temp_dir'}, $_ ); + $v->print( "Remove `" . $file . "'" ); + unlink $file or $stderr->print( "Could not remove `$file': $!" ); + next; + } # end if prefix + next; + } # end for readdir temp dir + closedir $dh_temp; + } # end if-else EPS files + } # end if-else keep files + + + if ( $Temp->{'eps_dir'} ) { + # EPS files in $Temp->{'eps_dir'} are always kept + $v->print( "As EPS directrory is set as `" . + $Temp->{'eps_dir'} . "', no EPS files there will be deleted." ); + + opendir my $dh_temp, $Temp->{'eps_dir'} or + die "Cannot open `" . $Temp->{'eps_dir'} . ": $!"; + for ( sort readdir $dh_temp ) { + next if ( / # omit files starting with a dot + ^ + \. + /x ); + if ( / + ^ + $Args->{'prefix'} + _ + .* + \.eps + $ + /x ) { + my $file = File::Spec->catfile( $Temp->{'eps_dir'}, $_ ); + $v->print( "- " . $file ); + next; + } # end if *.eps + next; + } # end for sort readdir + closedir $dh_temp; + + } + + 1; +} # end package Clean + + +1; +######################################################################## +### Emacs settings +# Local Variables: +# mode: CPerl +# End: diff --git a/contrib/glilypond/oop_fh.pl b/contrib/glilypond/oop_fh.pl new file mode 100644 index 00000000..36ee4f73 --- /dev/null +++ b/contrib/glilypond/oop_fh.pl @@ -0,0 +1,311 @@ +my $License = q* +######################################################################## +# Legalese +######################################################################## + +Source file position: `<groff-source>/contrib/glilypond/oop_fh.pl' +Installed position: `<prefix>/lib/groff/glilypond/oop_fh.pl' + +Copyright (C) 2013 Free Software Foundation, Inc. + Written by Bernd Warken <groff-bernd.warken-72@web.de> + +Last update: 10 May 2013 + +This file is part of `glilypond', which is part of `GNU groff'. + +glilypond - integrate `lilypond' into `groff' files + + `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 +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/>. +*; + +##### end legalese + + +# use strict; +# use warnings; +# use diagnostics; + +use integer; + +######################################################################## +# OOP for writing file handles that are open by default, like STD* +######################################################################## + +# -------------------------- _FH_WRITE_OPENED -------------------------- + +{ # FH_OPENED: base class for all opened file handles, like $TD* + + package _FH_WRITE_OPENED; + use strict; + + sub new { + my ( $pkg, $std ) = @_; + bless { + 'fh' => $std, + } + } + + sub open { + } + + sub close { + } + + sub print { + my $self = shift; + for ( @_ ) { + print { $self->{'fh'} } $_; + } + } + +} + + +# ------------------------------ FH_STDOUT ---------------------------- + +{ # FH_STDOUT: print to noral output STDOUT + + package FH_STDOUT; + use strict; + @FH_STDOUT::ISA = qw( _FH_WRITE_OPENED ); + + sub new { + &_FH_WRITE_OPENED::new( '_FH_WRITE_OPENED', *STDOUT ); + } + +} # end FH_STDOUT + + +# ------------------------------ FH_STDERR ----------------------------- + +{ # FH_STDERR: print to STDERR + + package FH_STDERR; + use strict; + @FH_STDERR::ISA = qw( _FH_WRITE_OPENED ); + + sub new { + &_FH_WRITE_OPENED::new( 'FH_OPENED', *STDERR ); + } + +} # end FH_STDERR + + +######################################################################## +# OOP for file handles that write into a file or string +######################################################################## + +# ------------------------------- FH_FILE ------------------------------ + +{ # FH_FILE: base class for writing into a file or string + + package FH_FILE; + use strict; + + sub new { + my ( $pkg, $file ) = @_; + bless { + 'fh' => undef, + 'file' => $file, + 'opened' => main::FALSE, + } + } + + sub DESTROY { + my $self = shift; + $self->close(); + } + + sub open { + my $self = shift; + my $file = $self->{'file'}; + if ( $file && -e $file ) { + die "file $file is not writable" unless ( -w $file ); + die "$file is a directory" if ( -d $file ); + } + open $self->{'fh'}, ">", $self->{'file'} + or die "could not open file `$file' for writing: $!"; + $self->{'opened'} = main::TRUE; + } + + sub close { + my $self = shift; + close $self->{'fh'} if ( $self->{'opened'} ); + $self->{'opened'} = main::FALSE; + } + + sub print { + my $self = shift; + $self->open() unless ( $self->{'opened'} ); + for ( @_ ) { + print { $self->{'fh'} } $_; + } + } + +} # end FH_FILE + + +# ------------------------------ FH_STRING ----------------------------- + +{ # FH_STRING: write into a string + + package FH_STRING; # write to \string + use strict; + @FH_STRING::ISA = qw( FH_FILE ); + + sub new { + my $pkg = shift; # string is a reference to scalar + bless + { + 'fh' => undef, + 'string' => '', + 'opened' => main::FALSE, + } + } + + sub open { + my $self = shift; + open $self->{'fh'}, ">", \ $self->{'string'} + or die "could not open string for writing: $!"; + $self->{'opened'} = main::TRUE; + } + + sub get { # get string, move to array ref, close, and return array ref + my $self = shift; + return '' unless ( $self->{'opened'} ); + my $a = &string2array( $self->{'string'} ); + $self->close(); + return $a; + } + +} # end FH_STRING + + +# -------------------------------- FH_NULL ----------------------------- + +{ # FH_NULL: write to null device + + package FH_NULL; + use strict; + @FH_NULL::ISA = qw( FH_FILE FH_STRING ); + + use File::Spec; + + my $devnull = File::Spec->devnull(); + $devnull = '' unless ( -e $devnull && -w $devnull ); + + sub new { + my $pkg = shift; + if ( $devnull ) { + &FH_FILE::new( $pkg, $devnull ); + } else { + &FH_STRING::new( $pkg ); + } + } # end new() + +} # end FH_NULL + + +######################################################################## +# OOP for reading file handles +######################################################################## + +# ---------------------------- FH_READ_FILE ---------------------------- + +{ # FH_READ_FILE: read a file + + package FH_READ_FILE; + use strict; + + sub new { + my ( $pkg, $file ) = @_; + die "File `$file' cannot be read." unless ( -f $file && -r $file ); + bless { + 'fh' => undef, + 'file' => $file, + 'opened' => main::FALSE, + } + } + + sub DESTROY { + my $self = shift; + $self->close(); + } + + sub open { + my $self = shift; + my $file = $self->{'file'}; + if ( $file && -e $file ) { + die "file $file is not writable" unless ( -r $file ); + die "$file is a directory" if ( -d $file ); + } + open $self->{'fh'}, "<", $self->{'file'} + or die "could not read file `$file': $!"; + $self->{'opened'} = main::TRUE; + } + + sub close { + my $self = shift; + close $self->{'fh'} if ( $self->{'opened'} ); + $self->{'opened'} = main::FALSE; + } + + sub read_line { + # Read 1 line of the file into a chomped string. + # Do not close the read handle at the end. + my $self = shift; + $self->open() unless ( $self->{'opened'} ); + + my $res; + if ( defined($res = CORE::readline($self->{'fh'}) ) ) { + chomp $res; + return $res; + } else { + $self->close(); + return undef; + } + } + + sub read_all { + # Read the complete file into an array reference. + # Close the read handle at the end. + # Return array reference. + my $self = shift; + $self->open() unless ( $self->{'opened'} ); + + my $res = []; + my $line; + while ( defined ( $line = CORE::readline $self->{'fh'} ) ) { + chomp $line; + push @$res, $line; + } + $self->close(); + $self->{'opened'} = main::FALSE; + return $res; + } + +} + +# end of OOP definitions + +package main; + +1; +######################################################################## +### Emacs settings +# Local Variables: +# mode: CPerl +# End: diff --git a/contrib/glilypond/subs.pl b/contrib/glilypond/subs.pl new file mode 100644 index 00000000..fa713d14 --- /dev/null +++ b/contrib/glilypond/subs.pl @@ -0,0 +1,469 @@ +my $License = q* +######################################################################## +# Legalese +######################################################################## + +Subroutines for `glilypond'. + +Source file position: `<groff-source>/contrib/glilypond/subs.pl' +Installed position: `<prefix>/lib/groff/glilypond/subs.pl' + +Copyright (C) 2013 Free Software Foundation, Inc. + Written by Bernd Warken <groff-bernd.warken-72@web.de> + + Last update: 10 May 2013 + +This file is part of `glilypond', which 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 +option) any later version. + + `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/>. +*; + +##### end legalese + + +# use strict; +# use warnings; +# use diagnostics; + +use integer; +use utf8; +use feature 'state'; + + +######################################################################## +# subs for using several times +######################################################################## + +sub create_ly2eps { # `--ly2eps' default + our ( $out, $Read, $Temp ); + + 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 + my $opts = '--ps -dbackend=eps -dinclude-eps-fonts -dgs-load-fonts ' . + "--output=$prefix $prefix"; + &run_lilypond("$opts"); + + Cwd::chdir $Temp->{'cwd'} or + die "Could not change to former directory `" . + $Temp->{'cwd'} . "': $!"; + + my $eps_dir = $Temp->{'eps_dir'}; + my $dir = $Temp->{'temp_dir'}; + opendir( my $dh, $dir ) or + die "could not open temporary directory `$dir': $!"; + + my $re = qr< + ^ + $prefix + - + .* + \.eps + $ + >x; + my $file; + while ( readdir( $dh ) ) { + chomp; + $file = $_; + if ( /$re/ ) { + my $file_path = File::Spec->catfile($dir, $file); + if ( $eps_dir ) { + my $could_copy = FALSE; + File::Copy::copy($file_path, $eps_dir) + and $could_copy = TRUE; + if ( $could_copy ) { + unlink $file_path; + $file_path = File::Spec->catfile($eps_dir, $_); + } + } + $out->print( '.PSPIC ' . $file_path ); + } + } # end while readdir + closedir( $dh ); +} # end sub create_ly2eps() + + +sub create_pdf2eps { # `--pdf2eps' + our ( $v, $stdout, $stderr, $out, $Read, $Temp ); + + my $prefix = $Read->{'file_numbered'}; # with dir change to temp dir + + &run_lilypond("--pdf --output=$prefix $prefix"); + + my $file_pdf = $prefix . '.pdf'; + my $file_ps = $prefix . '.ps'; + + # pdf2ps in temp dir + my $temp_file = &next_temp_file; + $v->print( "\n##### run of `pdf2ps'" ); + # `$ pdf2ps file.pdf file.ps' + my $output = `pdf2ps $file_pdf $file_ps 2> $temp_file`; + die 'Program pdf2ps does not work.' if ( $? ); + &shell_handling($output, $temp_file); + $v->print( "##### end run of `pdf2ps'\n" ); + + # ps2eps in temp dir + $temp_file = &next_temp_file; + $v->print( "\n##### run of `ps2eps'" ); + # `$ ps2eps file.ps' + $output = `ps2eps $file_ps 2> $temp_file`; + die 'Program ps2eps does not work.' if ( $? ); + &shell_handling($output, $temp_file); + $v->print( "##### end run of `ps2eps'\n" ); + + # change back to former dir + Cwd::chdir $Temp->{'cwd'} or + die "Could not change to former directory `" . + $Temp->{'cwd'} . "': $!"; + + # handling of .eps file + my $file_eps = $prefix . '.eps'; + my $eps_path = File::Spec->catfile($Temp->{'temp_dir'}, $file_eps); + if ( $Temp->{'eps_dir'} ) { + my $has_copied = FALSE; + File::Copy::copy( $eps_path, $Temp->{'eps_dir'} ) + and $has_copied = TRUE; + if ( $has_copied ) { + unlink $eps_path; + $eps_path = File::Spec->catfile( $Temp->{'eps_dir'}, $file_eps ); + } else { + $stderr->print( "Could not use EPS-directory." ); + } # end Temp->{'eps_dir'} + } + # print into groff output + $out->print( '.PSPIC ' . $eps_path ); +} # end sub create_pdf2eps() + + +sub is_subdir { # arg1 is subdir of arg2 (is longer) + my ( $dir1, $dir2 ) = @_; + $dir1 = &path2abs( $dir1 );; + $dir2 = &path2abs( $dir2 );; + my @split1 = File::Spec->splitdir($dir1); + my @split2 = File::Spec->splitdir($dir2); + for ( @split2 ) { + next if ( $_ eq shift @split1 ); + return FALSE; + } + return TRUE; +} + + +sub license { + our ( $Legalese, $stdout ); + &version; + $stdout->print( $Legalese->{'license'} ); +} # end sub license() + + +sub make_dir { # make directory or check if it exists + our ( $v, $Args ); + + my $dir_arg = shift; + chomp $dir_arg; + $dir_arg =~ s/^\s*(.*)\s*$/$1/; + + unless ( $dir_arg ) { + $v->print( "make_dir(): empty argument" ); + return FALSE; + } + + unless ( File::Spec->file_name_is_absolute($dir_arg) ) { + my $res = Cwd::realpath($dir_arg); + $res = File::Spec->canonpath($dir_arg) unless ( $res ); + $dir_arg = $res if ( $res ); + } + + return $dir_arg if ( -d $dir_arg && -w $dir_arg ); + + + # search thru the dir parts + my @dir_parts = File::Spec->splitdir($dir_arg); + my @dir_grow; + my $dir_grow; + my $can_create = FALSE; # dir could be created if TRUE + + DIRPARTS: for ( @dir_parts ) { + push @dir_grow, $_; + next DIRPARTS unless ( $_ ); # empty string for root directory + + # from array to path dir string + $dir_grow = File::Spec->catdir(@dir_grow); + + next DIRPARTS if ( -d $dir_grow ); + + if ( -e $dir_grow ) { # exists, but not a dir, so must be removed + die "Couldn't create dir `$dir_arg', it is blocked by `$dir_grow'." + unless ( -w $dir_grow ); + + # now it's writable, but not a dir, so it can be removed + unlink ( $dir_grow ) or + die "Couldn't remove `$dir_grow', " . + "so I cannot create dir `$dir_arg': $!"; + } + + # $dir_grow does no longer exist, so the former dir must be writable + # in order to create the directory + pop @dir_grow; + $dir_grow = File::Spec->catdir(@dir_grow); + + die "`$dir_grow' is not writable, " . + "so directory `$dir_arg' can't be createdd." + unless ( -w $dir_grow ); + + # former directory is writable, so `$dir_arg' can be created + + File::Path::make_path( $dir_arg, + { + mask => oct('0700'), + verbose => $Args->{'verbose'}, + } + ) # `mkdir -P' + or die "Could not create directory `$dir_arg': $!"; + + last DIRPARTS; + } + + die "`$dir_arg' is not a writable directory" + unless ( -d $dir_arg && -w $dir_arg ); + + return $dir_arg; + +} # end sub make_dir() + + +my $number = 0; +sub next_temp_file { + our ( $Temp, $v, $Args ); + ++$number; + my $temp_basename = $Args->{'prefix'} . '_temp_' . $number; + my $temp_file = File::Spec->catfile( $Temp->{'temp_dir'} , + $temp_basename ); + $v->print( "next temporary file: `$temp_file'" ); + return $temp_file; +} # end sub next_temp_file() + + +sub path2abs { + our ( $Temp, $Args ); + + my $path = shift; + $path =~ s/ + ^ + \s* + ( + .* + ) + \s* + $ + /$1/x; + + die "path2abs(): argument is empty." unless ( $path ); + + # Perl does not support shell `~' for home dir + if ( $path =~ / + ^ + ~ + /x ) { + if ( $path eq '~' ) { # only own home + $path = File::HomeDir->my_home; + } elsif ( $path =~ m< + ^ + ~ / + ( + .* + ) + $ + >x ) { # subdir of own home + $path = File::Spec->catdir( $Temp->{'cwd'}, $1 ); + } elsif ( $path =~ m< + ^ + ~ + ( + [^/]+ + ) + $ + >x ) { # home of other user + $path = File::HomeDir->users_home($1); + } elsif ( $path =~ m< + ^ + ~ + ( + [^/]+ + ) + /+ + ( + .* + ) + $ + >x ) { # subdir of other home + $path = File::Spec-> + catdir( File::HomeDir->users_home($1), $2 ); + } + } + + $path = File::Spec->rel2abs($path); + + # now $path is absolute + return $path; +} # end sub path2abs() + + +sub run_lilypond { + # arg is the options collection for `lilypond' to run + # either from ly or pdf + + our ( $Temp, $v ); + + my $opts = shift; + chomp $opts; + + my $temp_file = &next_temp_file; + my $output = EMPTYSTRING; + + # change to temp dir + Cwd::chdir $Temp->{'temp_dir'} or + die "Could not change to temporary directory `" . + $Temp->{'temp_dir'} . "': $!"; + + $v->print( "\n##### run of `lilypond " . $opts . "'" ); + $output = `lilypond $opts 2>$temp_file`; + die "Program lilypond does not work, see `$temp_file': $?" + if ( $? ); + chomp $output; + &shell_handling($output, $temp_file); + $v->print( "##### end run of `lilypond'\n" ); + + # stay in temp dir +} # end sub run_lilypond() + + +sub shell_handling { + # Handle ``-shell-command output in a string (arg1). + # stderr goes to temporary file $TempFile. + + our ( $out, $v, $Args ); + + my $out_string = shift; + my $temp_file = shift; + + my $a = &string2array($out_string); # array ref + for ( @$a ) { + $out->print( $_ ); + } + + $temp_file && -f $temp_file && -r $temp_file || + die "shell_handling(): $temp_file is not a readable file."; + my $temp = new FH_READ_FILE($temp_file); + my $res = $temp->read_all(); + for ( @$res ) { + chomp; + $v->print($_); + } + + unlink $temp_file unless ( $Args->{'keep_all'} ); +} # end sub shell_handling() + + +sub string2array { + my $s = shift; + my @a = (); + for ( split "\n", $s ) { + chomp; + push @a, $_; + } + return \@a; +} # end string2array() + + +sub usage { # for `--help' + our ( $Globals, $Args ); + + my $p = $Globals->{'prog'}; + my $usage = EMPTYSTRING; + $usage = '###### usage:' . "\n" if ( $Args->{'verbose'} ); + $usage .= qq*Options for $p: +Read a `roff' file or standard input and transform `lilypond' parts +(everything between `.lilypond start' and `.lilypond end') into +`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. + + +# Breaking options: +$p -?|-h|--help|--usage # usage +$p --version # version information +$p --license # the license is GPL >= 3 + + +# Normal options: +$p [options] [--] [filename ...] + +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 + +-k|--keep_all do not delete any temporary files +-v|--verbose print much information to STDERR + +Options with an argument: +-e|--eps_dir=... use a directory for the EPS files +-o|--output=... sent output in the groff language into file ... +-p|--prefix=... start for the names of temporary files +-t|--temp_dir=... provide the directory for temporary files. + +The directories set are created when they do not exist. +*; + + # old options: + # --keep_files -k: do not delete any temporary files + # --file_prefix=... -p: start for the names of temporary files + + $main::stdout->print( $usage ); +} # end sub usage() + + +sub version { # for `--version' + our ( $Globals, $Legalese, $stdout, $Args ); + my $end; + if ( $Globals->{'groff_version'} ) { + $end = " version $Globals->{'groff_version'}"; + } else { + $end = '.'; + } + + my $output = EMPTYSTRING; + $output = "###### version:\n" if ( $Args->{'verbose'} ); + $output .= "`" . $Globals->{'prog'} . "' version `" . + $Legalese->{'version'} . "' of `" . + $Legalese->{'last_update'} . "' is part of `GNU groff'" . $end; + + $stdout->print($output); +} # end sub version() + + +# end of subs + +1; +######################################################################## +### Emacs settings +# Local Variables: +# mode: CPerl +# End: |