diff options
author | Karl Berry <karl@freefriends.org> | 2010-07-19 23:16:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-07-19 23:16:46 +0000 |
commit | 277ca449c86a187fe858defdcd6aa1830d3b2d0d (patch) | |
tree | a804dd4e397504655fc225e6f582554780c4115d /Master/texmf-dist/source/latex/stex/bin | |
parent | d515f1120311798486a522c56170bd519d9c6a7a (diff) |
reinstate stex via new .tds.zip
git-svn-id: svn://tug.org/texlive/trunk@19538 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/stex/bin')
23 files changed, 3488 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/stex/bin/Makefile b/Master/texmf-dist/source/latex/stex/bin/Makefile new file mode 100644 index 00000000000..c603315a964 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/Makefile @@ -0,0 +1,5 @@ +all: + +clean: + rm -f *~ + diff --git a/Master/texmf-dist/source/latex/stex/bin/Modparse.pm b/Master/texmf-dist/source/latex/stex/bin/Modparse.pm new file mode 100644 index 00000000000..3c4cc8c9dd4 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/Modparse.pm @@ -0,0 +1,189 @@ +####################################################################################### +# A module for loading .tex files and feeding the data to the various applications. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/Modparse.pm$ # +# $Date: 2005-09-26 12:44:28 -0500 (Mon, 26 Sep 2005) $ $Rev: 4243 $ # +####################################################################################### + +package Modparse; + +use File::Basename; +use File::Path; + +# if both snippath and snippathList are specified, +# snippathList is ignored ! + +# if a default snippath definition file is found +# (snippath.def) it is used if no snippath is given +# as argument; +sub new { + my ($class, %options) = @_; + + $options{recursion} = 1 unless defined $options{recursion}; + $options{requireStatus} = 'include|exclude' unless defined $options{requireStatus}; + $options{loadInputs} = 1 unless defined $options{loadInputs}; + $options{onlyModuleLines} = 0 unless defined $options{onlyModuleLines}; + + if ( !(%{$options{snippath}}) && (-e "snippath.def") ) { + open(SNIPPATHDEF, 'snippath.def'); + my @snlist = <SNIPPATHDEF>; + close(SNIPPATHDEF); + for (my $i = 0 ; $i <= $#snlist; $i++) { chomp($snlist[$i]); } + %{$options{snippath}} = @snlist; } + @{$options{snippathList}} = keys(%{$options{snippath}}) + if ($options{snippath} && %{$options{snippath}}); + $options{debug} = 0; + + bless(\%options, $class); } + +sub execute{ + my ($self, $file) = @_; + + local *run_event = sub { + my ($event, $arg) = @_; + if ($self->{$event}) { $self->{$event}($arg); } + }; + + local *go = sub { + my ($location, %param) = @_; + my ($tex, $path, @tex_data) = $self->readLocation($location); + return unless @tex_data; + my $NL = $#tex_data+1; + + $param{filename} = $tex; + $param{depth}++; + $param{filecount}++; + my $i = 0; + + $param{nextline} = sub { $tex_data[++$i]; }; + $param{prevline} = sub { $tex_data[--$i]; }; + $param{rewriteline}= sub { $tex_data[$i] = $_[0]; }; + + print "Processing $tex...\n" if $self->{verbose}; + run_event('onBeginFile', \%param); + + while ($i<$NL){ + $param{original} = $tex_data[$i]; + $_ = $tex_data[$i]; chomp; /([^%]*)((%.*)?)/; + ($param{tex}, $param{comment}) = ($1, $2); $_ = $1; + s/\s+//g; $param{simple_tex} = $_; + + if (/\\begin\{module\}(\[([^\]]*)\])?/) { + if ($param{in_module}) { + push(@{$param{module_stack}}, [$param{module_id}, $param{module_arg}]); } + $param{in_module} = 1; + $param{module_args} = $1 ? $2 : undef; + $param{module_id} = ($param{module_args} && + $param{module_args} =~ /id=([^\],]+)/) ? $1 : undef; + $param{module_nesting}++; + run_event('onBeginModule', \%param); } + + if (/\\end\{module\}/) { + run_event('onEndModule', \%param); + if ($#{$param{module_stack}} >= 0) { + ($param{module_id}, $param{module_args}) = @{pop(@{$param{module_stack}})}; + } else { + $param{in_module} = 0; + ($param{module_id}, $param{module_args}) = (undef, undef); } + $param{module_nesting}--; + } + + foreach my $srch_snippath(@{$self->{snippathList}}){ + $self->{snippath}{$srch_snippath} = $1 + if (/\\def\\$srch_snippath\#1\{([^\#]+)\#1\}$/); } + + if (/\\((requiremodules(\[($self->{requireStatus})\])?)|input|include)\{([^\}]+)\}/){ + my $req_filename = $5; my $req_spath = ''; my $command = $1; + my $is_require = ($command =~ /requiremodules/) ? 1 : 0; + if ($is_require || $self->{loadInputs}) { + foreach my $srch_snippath(@{$self->{snippathList}}){ + if ($req_filename =~ /\\$srch_snippath\{(.+)/){ + ($req_spath, $req_filename) = ($self->{snippath}{$srch_snippath}, $1); + last; }} + run_event('onRecurse', \%param); + if ($self->{recursion} || !$is_require) { + go($self->makeLocation($req_filename, $path, $req_spath), %param); } + } + } + run_event('onEveryLine', \%param) if ($param{in_module} || !$self->{onlyModuleLines}); + + last if (/\\end\{document\}/ && $self->{stopAtEnd}); + $i++; + } + run_event('onEndFile', \%param); + $param{depth}--; return; + }; + + my %param = (pack=>$self, perm=>$self->{_AUX_DATA}, depth=>0, filecount=>0, + in_module=>0, module_nesting=>0); + run_event('onBegin', \%param); + go($self->makeLocation($file), %param); + run_event('onEnd', \%param); + return; +} + + +# add a [.tex] extension to the filename +sub add_ext{ + my ($self, $fn, $ext) = @_; + $ext = '.tex' unless $ext; + $fn.=$ext if $fn !~ /\Q$ext\E$/; + $fn; } + +# as long as the extension is .tex, drop it +sub drop_ext{ + my ($self, $filename) = @_; + while ($filename =~ /\.tex$/){ + while ($filename !~ /\.$/ ) { chop($filename); } + chop($filename); } + $filename; } + +sub new_ext{ + my ($self, $filename, $ext) = @_; + $self->add_ext($self->drop_ext($filename), $ext); } + +# location = pointer to array of strings +# first element is filename; next are possible paths +sub makeLocation{ my $self = shift; return \@_; } + +# read a location into an array of strings +# aslo return filename and path to it (just in +# case some changes were made to it, like adding +# extension and/or relative paths) +sub readLocation{ + my ($self, $location) = @_; + + my ($filename, @paths) = @{$location}; + # try to add proper extension; + my $filename_ext = $self->new_ext($filename) unless -e $filename; + $filename = $filename_ext if $filename_ext && -e $filename_ext; + + # try search paths + if (! -e $filename){ + my $all_p = ''; + foreach my $p(@paths){ + $all_p .= $p; + $filename = $all_p.$filename and last if -e $all_p.$filename; + $filename = $p.$filename and last if -e $p.$filename; + if ($filename_ext){ + $filename = $all_p.$filename_ext and last if -e $all_p.$filename_ext; + $filename = $p.$filename_ext and last if -e $p.$filename_ext; } + }} + # don't do the same work too many times + foreach my $file(@{$self->{loadedFiles}}) + { return undef if $file eq $filename; } + + push(@{$self->{loadedFiles}}, $filename); + open(FIN, $filename) or die "Cannot open '$filename'\n"; + my @data = <FIN>; + close(FIN); + + # find path of current file + my $path = dirname($filename); + $path.='/' if ($path ne ''); + + return ($filename, $path, @data); +} + +1; diff --git a/Master/texmf-dist/source/latex/stex/bin/README b/Master/texmf-dist/source/latex/stex/bin/README new file mode 100644 index 00000000000..6af84e42bab --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/README @@ -0,0 +1,151 @@ +msplit +"Module Split" + +Usage: + msplit <input filename> [options] + +Options: + --output <filename> filename of new main .tex file; default stdout + --path <path> path where to write the module files; + --header <filename> filename of header file to be included in all new .tex files + --verbose verbose on + --stop stop when \end{document} is found, not at EOF + --help show help screen + + +NOTE: All options '--xoption' can be replaced by '-x' as long as there is only one option starting with 'x' + +This program splits the .tex file given at input into: + one main .tex file, that includes + more .tex files, each containing one module + +The name of the new main .tex file is specified by output option. The path to the inputted +files can be specified by path. The name of one generated input file is "name of the +module it contains".tex Running on one already split file will just make a copy. Example +usage: ./msplit slides.tex -o sl.tex -p ./modules -s + +Interpretation: "Split the file slides.tex; wite the new main file as sl.tex and the +inputted files should be placed in ./modules; if path does not exist, it is automatically +created; stop when (uncommented) \end{document} is found." + + + +rf +"Reuse Factor" + +Usage: + rf [options] + +Options: + --input <filename> .tex input file. stdin by default + --stop stop when \end{document} is found, not at EOF + --verbose verbose on + --help show help screen + + +This program computes the reuse factor for the .tex document given at input. This number +represents the ratio of latex processed lines of code to actual lines contained in file +given at input. This number will always be 1 for files that have no \input or \include. + +Example usage: +./rf -v -i slides.tex +Interpretation: "Compute the reuse factor of slides.tex and show all processed files(verbose mode)." + + + +sgraph +"Slides graph [representation]" + +Usage: + sgraph [options] + +Options: + --input <filename> .tex input file; stdin by default + --output <filename> output file; out.dot by default + --format <ps|png|jpg|...> output format; .ps by default; for available formats, see dot --help + --nodot do not generate .dot file, just target format + --root <string> the 'root' of the graph. (name of course) + --theory <string> generate a subgraph for the theory + --sliderange <begin:end> only look at the given slide range; (2:16 for example) + --stop stop reading data when \end{document} is found, not at EOF + --verbose verbose on + --help show help screen + +This program generates a .dot file readable by graphviz, containing a graph of the module +usage in the .tex file given at input, optionally looking at a specific theory and/or +slide range; it also adds a dummy 'root' for the graph, so one can see where everything +starts. It then converts the .dot file to a given format (.ps by default) using graphviz +and optionally deletes the intermediary .dot file. + +Example usage: +./sgraph -i slides.tex -o graph -f ps -n -t TCN --sliderange 20:10000 -r GenCS -v + +Interpretation: "Generate the graph of slides.tex in .ps format, write it in graph.ps, do +not keep the .dot file; include only the part needed for the theory 'TCN' and in the slide +range 20 to 10000; use as root for the graph the string 'GenCS' and show all processed +files." + + +sms +?? + +Usage: + sms [options] + +Options: + --input <filename> .tex file to split; default stdin + --verbose verbose on + --stop stop when \end{document} is found, not at EOF + --help show help screen + +Generate .sms file from .tex file given at input; .sms files contain only the modules and +the macros defined within, no other text. + +Example usage: +./sms -i slides.tex -s + +Interpretation: "Generate the slides.sms file for slides.tex; Stop when \end{document} is found." + + + + +bms +"Build Module Structure" + +Usage: + bms [options] + +Options: + --input <filename> .tex file to read from + --graph <filename> if mentioned, produce the suggested module structure as + a graphviz digraph (.dot file) + --path <pathname> if mentioned, produce same input file/s (including + dependencies) in specified path with suggested + module structure. + --output <filename> the new name of the main .tex file in specified path + --root <string> if mentioned, a father module is included, so that all + other modules descend from it. generally the course name + --stop stop when \end{document} is found; default is to go on + --definitions show a list of all definitions + --verbose verbose on + --help show help screen + + +This program has the purpose of computing a default module structure, such that a module +uses another module if and only if it needs that module and does not need another +descendant of it. First, the prgram reads all necessary data from the input .tex file, +computes the minimal strictly required module usage structure, and writes it as a graphviz +digraph, and/or writes a copy of the input .tex file (and maybe inputted files by the .tex +file) with the new module structure in the given path. All paths are created if not +existing. + +Example usage: +./bms -i slides.tex -s -g - | dot -Tps > out.ps; ggv out.ps +./bms -i slides.tex -g out.dot -p ./new + +Interpretation: "Build default module structure for slides.tex and write it to out.dot; +also use the obtained module structure and copy the input file to given path with changed +module usage." + +rng2dot +Convert Relax NG Compact form to Graphviz dot file diff --git a/Master/texmf-dist/source/latex/stex/bin/TexId.pm b/Master/texmf-dist/source/latex/stex/bin/TexId.pm new file mode 100644 index 00000000000..d0f28ccbce5 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/TexId.pm @@ -0,0 +1,464 @@ +# package for handling .tex IDs + +package TexId; + +use File::Basename; +use strict; + +# error messages markers + +use constant ERR => '[X]'; # error can't be fixed + +################### 'public' members ################### + +sub new{ + my ($class, %options) = @_; + my $self = {}; + + @{$self->{ENVIRONMENTS}} = qw(module note omtext example + definition problem proof + solution program); # the environments to look at + + @{$self->{ENV_PREFIXES}} = qw(mod not txt ex def prob pf sol prg); # the prefixes for environments + + + @{$self->{ENV_DEF}} = qw(id); # environment arguments that define new environments + @{$self->{ENV_USAGE}} = qw(use uses for from); # environment arguments that + # specify usage of other environments + + # options for the class + %{$self->{OPTIONS}} = %options; + + # in case \snippath{} is encountered, prepend this to the filename + $self->{OPTIONS}{snippath} = 'snippets/' unless defined $self->{OPTIONS}{snippath}; + + + # show progress while reading data + $self->{OPTIONS}{progress} = 1 unless defined $self->{OPTIONS}{progress}; + + bless ($self, $class); +} + +# check/set list of environments to look at +sub environments{ + my ($self, $new_environments, $new_prefixes) = @_; + if (defined $new_environments and defined $new_prefixes){ + @{$self->{ENVIRONMENTS}} = split(/,/, $new_environments); + @{$self->{ENV_PREFIXES}} = split(/,/, $new_prefixes); + die "Invalid argument combination (both arguments must have same number of elements)" + if $#{$self->ENVIRONMENTS} != $#{$self->ENV_PREFIXES}; + } + else { + return (join(',', @{$self->{ENVIRONMENTS}}), join(',', @{$self->{ENV_PREFIXES}})); + } +} + +# define/read environment definition arguments +sub env_def{ + my ($self, $new_env_def) = @_; + if (defined $new_env_def){ + @{$self->{ENV_DEF}} = split(/,/, $new_env_def); + } + else { + return join(',', @{$self->{ENV_DEF}}); + } +} + +# define/read the environment usage arguments +sub env_usage{ + my ($self, $new_env_usage) = @_; + if (defined $new_env_usage){ + @{$self->{ENV_USAGE}} = split(/,/, $new_env_usage); + } + else { + return join(',', @{$self->{ENV_USAGE}}); + } +} + +# define/read the snippets path +sub snippath{ + my ($self, $new_snippath) = @_; + if (defined $new_snippath){ + $new_snippath.='/' if ($new_snippath !~ /\/$/); + $self->{OPTIONS}{snippath} = $new_snippath; + } + else { + return $self->{OPTIONS}{snippath}; + } +} + + +# check all the definitions and module usages +# in all files referenced by base file +sub parse{ + + my ($self, $basefile) = @_; + + # recursive local function to go through each file + local *run_parse = sub + { + my ($filename) = @_; + + # read current .tex file + print STDERR "Loading $filename...\n" if ($self->{OPTIONS}{progress} == 1); + $filename = $self->load_file_data($filename); + my @text = @{$self->{FILEDATA}}; + my $line_no = 0; + + # go through every line of the read file + # depends on: \requiremodules, \snippath + # ignores \end{document} + + foreach (@text){ + # delete newline character, comments and redundant white space + + $line_no++; + /([^%]*)((%.*)?)/; + $_ = $1; + s/\s+//g; + + # see if an environment that has some arguments is defined + my ($possible_env, $env_args) = (undef, undef); + ($possible_env, $env_args) = ($1, $2) if (/\\begin\{([^\}]+)\}\[([^\]]+)\]/); + + # if it is, search it through the list of environments we want to look at + if (defined $possible_env){ + foreach my $environment(@{$self->{ENVIRONMENTS}}){ + next unless ($environment eq $possible_env); + + # if we found an anvironment we want to look at, + # go through the list of arguments + $env_args = $self->swap_exterior_char(',', ';', $env_args); + foreach (split(/;/, $env_args)){ + # we want arguments of type name=value + next unless /([^=]+)=(.+)/; + my ($arg_name, $arg_value) = ($1, $2); + + # see if the argument defines an environment + foreach my $current_env_arg(@{$self->{ENV_DEF}}){ + next unless ($arg_name eq $current_env_arg); + my @to_add = split(/,/, $arg_value); + push(@{$self->{'DEF'}->{$environment}}, @to_add); + foreach my $added_element(@to_add){ + $self->{'DEF'}->{LOCATION}{$added_element}.=$line_no.':'.$filename."\n"; + } + last; + } + + # see if the argument uses an environment + foreach my $current_env_arg(@{$self->{ENV_USAGE}}){ + next unless ($arg_name eq $current_env_arg); + my @to_add = split(/,/, $arg_value); + push(@{$self->{'USE'}->{$environment}}, @to_add); + foreach my $added_element(@to_add){ + $self->{'USE'}->{LOCATION}{$added_element}.=$line_no.':'.$filename."\n"; + } + last; + } + } + last; + } + } + # reference to another file + if (/\\requiremodules(\[(include|exclude)\])?\{([^\}]+)\}/){ + if (defined $2 && $2 eq 'include'){ + $_ = $3; + $_ = $self->{OPTIONS}{snippath}.$1 if (/\\snippath\{(.+)/); + $_ = $self->{path}.$_; + run_parse($_); + } + } + + # see definition of snippath + $self->snippath($1) if (/\\def\\snippath\#1\{([^\#]+)\#1\}$/); + } + }; + + run_parse($basefile); + +} + +# this is the first checking step to be done +sub check_uniq{ + + my ($self) = @_; + + my $error = 0; + + # sort environment definitions and see whether they are uniquely defined + foreach my $environment(@{$self->{ENVIRONMENTS}}){ + next unless defined $self->{'USE'}->{$environment}; + + my @list1 = sort @{$self->{'DEF'}->{$environment}}; + my @list2 = $self->uniq(@list1); + @{$self->{'DEF'}->{$environment}} = @list2; + + # some environments are defined multiple times + if ($#list1 != $#list2){ + my $j = 0; + for (my $i = 0; $i<=$#list2; $i++){ + my $start_j = $j; + while ($j<=$#list1 && $list1[$j] eq $list2[$i]){ + $j++; + } + if ($j - $start_j != 1){ + print STDERR ERR, " Environment '$list2[$i]' is defined multiple times ", + "within same environment type: \n"; + print STDERR $self->{'DEF'}->{LOCATION}{$list2[$i]}, "\n"; + $error = 1; + } + } + } + } + + # see that all environment references are unique (and sort them) + foreach my $environment(@{$self->{ENVIRONMENTS}}){ + next unless defined $self->{'USE'}->{$environment}; + @{$self->{'USE'}->{$environment}} = sort $self->uniq(@{$self->{'USE'}->{$environment}}); + } + + return $error; +} + +sub check_prefix{ + + my ($self) = @_; + + my $count = $#{$self->{ENVIRONMENTS}}+1; + + for (my $i = 0; $i < $count; $i++){ + my $environment = ${$self->{ENVIRONMENTS}}[$i]; + my $envprefix = ${$self->{ENV_PREFIXES}}[$i]; + next unless defined $self->{'DEF'}->{$environment}; + + foreach my $elem (@{$self->{'DEF'}->{$environment}}){ + + my $proper = undef; + if ($elem =~ /^([^:]+):(.+)/){ + $proper = $envprefix.':'.$2 if $1 ne $envprefix; + } else { + $proper = $envprefix.':'.$elem; + } + + if (defined $proper){ + print STDERR ERR, " $environment '$elem' has no prefix ($envprefix). Add it? [ <y>, n ]"; + my $answer = <STDIN>; + chomp($answer); + if ($answer eq 'y' or $answer eq ''){ + $self->add_change('DEF', $elem, $proper); + } + } + } + } +} + + +sub check_defs{ + my ($self) = @_; + + my $error = 0; + + # combine all definitions + my @defs; + map {push(@defs, @{$self->{'DEF'}->{$_}}) if defined @{$self->{'DEF'}->{$_}}} @{$self->{ENVIRONMENTS}}; + @defs = sort @defs; + + # combine all used environments + my @uses; + map {push(@uses, @{$self->{'USE'}->{$_}}) if defined @{$self->{'USE'}->{$_}}} @{$self->{ENVIRONMENTS}}; + @uses = sort @uses; + + + # for all environments + + foreach my $used_env(@uses){ + # if used environment is not defined + if ($self->find_elem($used_env, @defs) < 0){ + # maybe it is a typo + print STDERR ERR, " '$used_env' was not found. Replace options:\n"; + foreach my $definition(@defs){ + print STDERR "\t$definition\n" if $self->edit_dist($used_env,$definition)<4; + $error = 1; + } + } + } + + return $error; +} + + +sub add_change{ + my ($self, $location, $from, $to) = @_; + if ($self->{$location}->{LOCATION}{$from} =~ /([^:]+):([^\n]+)\n/){ + push(@{$self->{CHANGE}->{$2}}, ($1, $from, $to)); + } +} + +# write the stored changes +sub apply_changes{ + my ($self) = @_; + while (my ($filename, $changes) = each %{$self->{CHANGE}}){ + $filename = $self->load_file_data($filename); + my $count = int(($#{$changes}+1)/3); + for (my $i = 0; $i<$count ; $i++){ + my ($line, $from, $to) = (${$changes}[$i*3]-1, + ${$changes}[$i*3+1], ${$changes}[$i*3+2]); + ${$self->{FILEDATA}}[$line] =~ s/\Q$from/$to/; + } + print STDERR "Writing $filename\n" if ($self->{OPTIONS}{progress} == 1); + $self->write_file_data($filename); + } +} + +sub load_file_data{ + my ($self, $filename) = @_; + + # try to give proper file extension if file is not found + $filename = $self->add_ext($self->drop_ext($filename)) unless -e $filename; + + open(FIN, $filename) or die "Cannot open $filename\n"; + @{$self->{FILEDATA}} = <FIN>; + close(FIN); + + $self->{path} = dirname($filename).'/' unless defined $self->{path}; + + return $filename; +} + +sub write_file_data{ + my ($self, $filename) = @_; + + open(FOUT, ">$filename") or die "Cannot write $filename\n"; + print FOUT @{$self->{FILEDATA}}; + close(FOUT); +} + + +################### 'protected' members ################### + +sub def_env_list{ + my ($self, $env_name) = @_; + return @{$self->{'DEF'}->{$env_name}}; +} + +sub use_env_list{ + my ($self, $env_name) = @_; + return @{$self->{'USE'}->{$env_name}}; +} + + +################### 'private' members ################### + +sub drop_ext{ + my ($self, $filename) = @_; + while ($filename =~ /\.tex$/){ + while ($filename !~ /\.$/ ) { chop($filename); } + chop($filename); + } + return $filename; +} + +sub add_ext{ + my ($self, $filename) = @_; + $filename.='.tex' if $filename !~ /\.tex$/; + return $filename; +} + +# look at $word, and swap all occurances of $char_find with +# $new_char if they are not in a {...} environment + +sub swap_exterior_char{ + my ($self, $char_find, $new_char, $word) = @_; + my @new_word = (); + my $exterior = 0; + foreach (split('', $word)){ + if ($_ eq '{'){ + $exterior++; + next; + } + + if ($_ eq '}'){ + $exterior--; + next; + } + + if ($exterior == 0 && $_ eq $char_find){ + push(@new_word, $new_char); + } + else{ + push(@new_word, $_); + } + } + return join('',@new_word); +} + +# return unique elements from a list +sub uniq{ + my ($self, @list) = @_; + my %seen = (); + my @uniqu = grep { ! $seen{$_} ++ } @list; + return @uniqu; +} + + +# binary search +sub find_elem{ + my ($self, $elem, @list) = @_; + + local *search_elem = sub + { + my ($a, $b) = @_; + my $m = int(($a + $b)/2); + return $m if $list[$m] eq $elem; + return -1 if ($a >= $b); + return ($list[$m] le $elem)?search_elem($m+1,$b):search_elem($a,$m-1); + }; + + return search_elem(0, $#list); +} + +# edit distance between two strings +# insertions, deletions, replacement, transposition +sub edit_dist{ + my ($self, $s1, $s2) = @_; + my $m = length($s1); + my $n = length($s2); + my @w1 = split(//, $s1); + my @w2 = split(//, $s2); + + # add dummy char so we can have nicer indeces + unshift(@w1, '*'); + unshift(@w2, '*'); + + # distances matrix + my @d; + + # initialize + $d[0][0] = 0; + for (my $i = 1; $i <= $m ; $i++) { $d[$i][0] = $i;} + for (my $i = 1; $i <= $n ; $i++) { $d[0][$i] = $i;} + + # compute + for (my $i = 1; $i <= $m ; $i++){ + for (my $j = 1; $j <= $n ; $j++){ + my @possibilities = ($d[$i-1][$j-1] + ($w1[$i] ne $w2[$j]), + $d[$i-1][$j] + 1, $d[$i][$j-1] + 1); + + push(@possibilities, $d[$i-2][$j-2] + 1) + if ($i>1 && $j>1 && $w1[$i] eq $w2[$j-1] && $w1[$i-1] eq $w2[$j]); + + $d[$i][$j] = $self->minimum(@possibilities); + } + } + return $d[$m][$n]; +} + +sub minimum{ + my ($self, @list) = @_; + my $result = shift(@list); + map {$result = $_ if $result ge $_} @list; + return $result; +} + + +1; diff --git a/Master/texmf-dist/source/latex/stex/bin/allgen b/Master/texmf-dist/source/latex/stex/bin/allgen new file mode 100755 index 00000000000..4728d89ee56 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/allgen @@ -0,0 +1,30 @@ +#!/bin/bash + +if [[ -z $STEX_CONTENT_HOME ]] +then + echo "STEX_CONTENT_HOME is not set; please set it in your ~/.bashrc" + exit 1 +fi + +LIB="$STEX_CONTENT_HOME/slides/lib" +cat <<'EOF' +% this file is automatically generated by allgen +% Note: This hack is needed to make mikoslides and problems work together. +\PassOptionsToPackage{solutions,notes,pts,min}{problems} +EOF + +sed -e '/\\begin{document}/ i\ +\\usepackage{problems} +' $LIB/pre.tex | \ + grep -v '^\\def\\snippets' + +cat <<'EOF' +EOF + +for file in *.tex +do + prefix=${file%.tex} # file name without .tex suffix + [[ $prefix != "all" ]] && echo -e "\\subsection{${prefix//_/\\\\_}} \n \\input{$prefix}" # in subsection replace "_" by "\_" +done + +cat $LIB/post.tex diff --git a/Master/texmf-dist/source/latex/stex/bin/bms b/Master/texmf-dist/source/latex/stex/bin/bms new file mode 100755 index 00000000000..52f1002c0d9 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/bms @@ -0,0 +1,340 @@ +#!/usr/bin/perl -w + +####################################################################################### +# A tool for building a default module usage structure. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/bms$ # +# $Date: 2005-10-04 10:47:41 -0500 (Tue, 04 Oct 2005) $ $Rev: 4371 $ # +####################################################################################### + +use strict; + +use Getopt::Long; +use File::Path; +use Pod::Usage; +use Modparse; + + +########################################## +# Command Line processing +########################################## + +my $input="-", my $graph_output='', my $graph_root='', +my $verbose=0, my $stop_at_end=0; +my $show_definitions=0, my $show_modules = 0; +my %arg_snippath; my @snippathList; + +$main::path_new=''; +$main::new_name=''; + +GetOptions("path=s" => \%arg_snippath, + "defpath=s" => \@snippathList, + "graph=s" => \$graph_output, + "opath=s" => \$main::path_new, + "output=s" => \$main::new_name, + "root=s" => \$graph_root, + "definitions" => sub {$show_definitions = 1;}, + "modules" => sub {$show_modules = 1;}, + "stop" => sub {$stop_at_end = 1;}, + "verbose" => sub {$verbose = 1;}, + "help" => sub {pod2usage(2);}); + +$input = $ARGV[0] if ($#ARGV>=0); + +########################################## +# .tex data reading +########################################## + +$main::no_name_modules = 0; +%main::definition_module = (); +@main::definitions_list = (); + +%main::module_definitions = (); +%main::used_modules = (); +@main::modules_list = (); + +my $mp = Modparse->new(snippathList=>\@snippathList, + snippath=>\%arg_snippath, + stopAtEnd=>$stop_at_end, + verbose=>$verbose, + requireStatus=>'exclude', + onlyModuleLines=>1, + onBeginModule=>sub { + if (!defined $_[0]->{module_id}) { + $_[0]->{module_id} = "MOD".$main::no_name_modules; + $main::no_name_modules++; } + $_[0]->{defines} = ''; + }, + onEveryLine=>sub { + if ($_[0]->{simple_tex} =~ /\\(sym|abbr|ell)def\{\\([^\}]+)\}/) { + my $data = $2; + $_[0]->{defines} .= "$data;"; + $main::definition_module{$data} = $_[0]->{module_id}; + push(@main::definitions_list, $data); + } elsif ($_[0]->{simple_tex} =~ /\\STRlabel\{([^\}]*)\}/){ + my $data = "L:$1"; + $_[0]->{defines} .= "$data;"; + $main::definition_module{$data} = $_[0]->{module_id}; + push(@main::definitions_list, $data); + } + $_[0]->{module_content} .= $_[0]->{simple_tex}; + }, + onEndModule=>sub { + chop($_[0]->{defines}) if $_[0]->{defines}; + $main::module_definitions{$_[0]->{module_id}} = $_[0]->{defines}; + push(@main::modules_list, $_[0]->{module_id}); + my $module_refs = ''; + foreach my $def(@main::definitions_list){ + next if $main::definition_module{$def} eq $_[0]->{module_id}; + next unless $module_refs !~ /$main::definition_module{$def}/; + if ($def =~ /^L\:(.*)/){ + $module_refs .= "$main::definition_module{$def};" + if ($_[0]->{module_content} =~ /\\STRcopy\{$1\}/); + } else { + $module_refs .= "$main::definition_module{$def};" + if ($_[0]->{module_content} =~ /\\$def/); + } + } + chop($module_refs) if $module_refs; + $main::used_modules{$_[0]->{module_id}} = $module_refs; + }); + +################################################################## +# Internal routines for BMS +################################################################## + +%main::bms = (); + +# add a dummy module that uses nothig, such that any other module uses at least something +sub addroot { + foreach my $module(@main::modules_list){ + next if $main::used_modules{$module}; + $main::used_modules{$module} = $graph_root; + } + push(@main::modules_list, $graph_root); + $main::module_definitions{$graph_root}=''; + $main::used_modules{$graph_root}=''; +} +# end addroot + +sub included { + my ($a1_ref, $a2_ref) = @_; + my $ok; + foreach my $elem (@$a1_ref){ + $ok = 0; + foreach (@$a2_ref){ + if ($elem eq $_){ + $ok=1; + last; }} + return 0 unless $ok;} + return 1; +} + +# find if a module uses another module +sub can_go{ + my ($src,$dest) = @_; + return 1 if $src eq $dest; + foreach (split(/;/, $main::bms{$src})){ + return 1 if can_go($_,$dest); + } + return 0; +} +# end can_go + +# find the actual module structure +sub find_bms{ + my @added_modules, my @can_add, my @to_look, my @next_step; + + %main::bms=(); + @to_look = @main::modules_list; + @added_modules = (); + + while($#main::modules_list != $#added_modules){ + + @can_add=(); @next_step=(); + + foreach my $module(@to_look){ + my @temp = split(/;/, $main::used_modules{$module}); + included(\@temp,\@added_modules)?push(@can_add,$module):push(@next_step,$module); + } + @to_look = @next_step; + + foreach my $module(@can_add){ + + my @uses = split(/;/,$main::used_modules{$module}); + my $change = 1; + while ($change){ + $change = 0; + foreach my $f1(@uses){ + foreach my $f2(@uses){ + next if $f1 eq $f2; + if (can_go($f1,$f2)){ # i.e. f2 used by f1 => can remove f2 + my @new_uses; + foreach (@uses){ + push(@new_uses,$_) unless ($_ eq $f2); + } + @uses = @new_uses; + $change = 1; + last; + } + } + last if $change; + } + } + $main::bms{$module} = join(";",@uses); + push(@added_modules,$module); + } + } +} +# end find_bms + +# print the content of %bms in a .dot file; note: may change %bms by adding dummy root +sub printgraph { + my $out = shift; + + addroot if $graph_root; + + open(FOUT,">$out") or die "Can't write $out\n"; + print FOUT "digraph MS {\n"; + while (my ($module, $uses) = each %main::bms){ + $uses =~ s/-/_/g; + $module =~ s/-/_/g; + if ($uses){ + if ($uses =~ /;/){ + print FOUT "$module -> {$uses};\n"; + } else { + print FOUT "$module -> $uses;\n"; + } + } else { + print FOUT "$module [shape=box color=red];\n"; + } + } + print FOUT "}\n"; + close(FOUT); +} +# end printgraph + +# print the list of definitions +sub printdefinitions{ + while (my ($module,$def) = each %main::module_definitions){ + print "$module:\n" if $def; + foreach (split(/;/,$def)){ + print "\t$_\n"; + } + }} +# end printdefinitions + +#print the list of modules +sub printmodules{ + while (my ($module,$uses) = each %main::used_modules){ + print "'$module' uses:\n $uses\n\n\n"; + }} +#end printmodules + + +# wite the new .tex file, with found module usage, in given path +sub writenew { + my ($filename) = @_; + $main::no_name_modules = 0; + my $wmp = Modparse->new(snippathList=>\@snippathList, + snippath=>\%arg_snippath, + stopAtEnd=>$stop_at_end, + verbose=>$verbose, + requireStatus=>'exclude', + onlyModuleLines=>0, + onBeginFile=> sub { + $_[0]->{'new_content'.$_[0]->{depth}} = ''; + }, + onBeginModule=>sub { + if (!defined $_[0]->{module_id}) { + $_[0]->{module_id} = "MOD".$main::no_name_modules; + $main::no_name_modules++; } + my $new_uses = $main::bms{$_[0]->{module_id}}; + if (defined $new_uses) { + $new_uses =~ s/;/,/g; + $new_uses="{$new_uses}" if $new_uses =~ /,/; + my $arg = $_[0]->{module_args}; + my @new_arg=(); + my $done = 0; + while ($arg =~ /^([\w-]+)=(([\w-]+)|(\{[\w,-]+\}))/){ + if ($1 eq 'uses'){ + push(@new_arg,"$1=$new_uses")if $new_uses; + $done = 1; + } else { + push(@new_arg,"$1=$2"); + } + $arg=substr($arg,length($1)+length($2)+1); + $arg=substr($arg,1) if ($arg =~ /^,/); + } + if ($new_uses) { + push(@new_arg,"uses=$new_uses") unless $done; } + $_[0]->{original} = "\\begin{module}\[".join(',',@new_arg)."\] ". $_[0]->{comment}. "\n"; + } + }, + onEveryLine=>sub { + $_[0]->{'new_content'.$_[0]->{depth}} .= $_[0]->{original}; + }, + onEndFile=> sub { + my $filename = ($main::path_new).'/'.$_[0]->{filename}; + my $path = $filename; + while ($path !~ m!\/$!) { chop($path); } + mkpath($path); + $filename = $path.'/'.$main::new_name if ($main::new_name && $_[0]->{depth} == 1); + print "Writing $filename\n" if $_[0]->{pack}->{verbose}; + open(FS, ">$filename") or die "Cannot write $filename\n"; + print FS $_[0]->{'new_content'.$_[0]->{depth}}; + close(FS); + }); + + $wmp->execute($filename); +} + + +############################################################# +# Start program +############################################################# + +$mp->execute($input); + +printdefinitions if $show_definitions; +printmodules if $show_modules; + +if ($graph_output || $main::path_new){ + find_bms; + writenew($input) if $main::path_new; + printgraph($graph_output) if $graph_output; +} + +__END__ + + +=head1 SYNOPSIS + +bms <input filename> [options] + +Options: + + --path XXX specify the value of \XXX (some snippath) in case it is + = somePath not defined in the processed .tex file + --defpath XXX specify which \XXX (snippath definitions) to look for + --graph <filename> if mentioned, produce the suggested module structure as + a graphviz digraph. (.dot file) + --opath <pathname> if mentioned, produce same input file/s (including + dependencies) in specified path with suggested + module structure. + --output <name> the new name of the main .tex file in specified path. + --root <name> if mentioned, a father module is included, so that all + other modules descend from it. generally the course name. + --stop stop when \end{document} is found; default is to go on. + --definitions show a list of all definitions. + --modules show a list of all modules. + --verbose verbose on. + --help this screen. + + + This program has the purpose of computing a default module structure, according +to actual necessities. + Example: + ./bms -i slides.tex -g out.dot + ./bms -i slides.tex -s -g - | dot -Tps > out.ps; ggv out.ps diff --git a/Master/texmf-dist/source/latex/stex/bin/checksum b/Master/texmf-dist/source/latex/stex/bin/checksum new file mode 100755 index 00000000000..7e521deaa7c --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/checksum @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w +####################################################################################### +# A tool for updating .dtx files with a correspodning checksum counter # +# Copyright (c) 2010, Deyan Ginev, released under the Gnu General Public License (GPL)# +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: https://svn.kwarc.info/repos/stex/trunk/bin/checksum$ # +####################################################################################### + +use strict; + +use Getopt::Long; +use Modparse; +use Pod::Usage; +use Cwd qw(abs_path); + +####### start of program ####### +my $mode = "update"; #Default is update +my $action = { "update" => \&update, "disable" => \&disable, "enable"=>\&enable }; +GetOptions("disable" => sub { $mode="disable"; }, + "enable" => sub { $mode="enable"; }, + "update" => sub { $mode="update"; }); + + +my ($path) = @ARGV; +$path = abs_path($path); +my ($volume,$dir,$file) = File::Spec->splitpath( $path ); +my @lines = `cd $dir; pdflatex "\\nonstopmode\\input{$file}"` if ($mode eq "update"); +my ($checksum) = map {$_=~/^\* The checksum should be (\d+)!/; $1;} grep ($_ =~ /^\* The checksum should be (\d+)!/,@lines) if @lines; + +open(IN,"<$path") or die "Cannot open DTX source: $path\n"; +@lines = (); +while (<IN>) { + push @lines, &{$$action{$mode}}($_,$checksum); +} +close(IN); +open(OUT,">$path") or die "Cannot write to DTX target: $path\n"; +print OUT join("",@lines); +close(OUT); +######### Subroutines ############ +sub update { + my $checksum=$_[1]||"1"; + $_[0]=~s/\\CheckSum\{\d*\}/\\CheckSum{$checksum}/; + $_[0]; +} + +sub disable { + $_[0]=~s/\\CheckSum\{(\d*)\}/\\iffalse\\CheckSum\{$1}\\fi/ unless $_[0]=~/\\iffalse\\CheckSum\{(\d*)\}\\fi/; + $_[0]; +} + +sub enable { + $_[0]=~s/\\iffalse\\CheckSum\{(\d*)\}\\fi/\\CheckSum{$1}/; + $_[0]; +} + + +__END__ + + +=head1 SYNOPSIS + +checksum <input filename> --update|enable|disable + +Purpose: + Update, enable or disable the \CheckSum macro for a given .dtx source + +Example: + checksum omd.dtx --update diff --git a/Master/texmf-dist/source/latex/stex/bin/convert-paths b/Master/texmf-dist/source/latex/stex/bin/convert-paths new file mode 100755 index 00000000000..55ee72a2370 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/convert-paths @@ -0,0 +1,56 @@ +#!/usr/bin/perl -w +# +# A script that converts paths in sTeX files from the old \Foosnipppath{bar} +# to \snippets{foo/bar}, according to the definition of those path macros in +# paths.sty. +# +# Syntax: convert-paths path/to/paths.sty FILES +# +# © 2008 Christoph Lange, KWARC, Jacobs University + +use File::Copy; + +my %map; + +my $SNIPPATHRE = '\\\\[[:alnum:]]+(?i:snip|pic)path'; + +if (open(P, shift(@ARGV))) { + print STDERR "Mapping:\n"; + while (<P>) { + if (/^\\def($SNIPPATHRE)#1\{(\\KWARCslides\{[^#]+)#1\}/o) { + printf STDERR "\t%s -> %s\n", $1, $2; + $map{$1} = $2; + } + } + close(P); +} +else { + die "Could not open paths.sty"; +} + +print STDERR "Processing files:\n"; +while ($#ARGV >= 0) { + my $filename = shift(@ARGV); + print STDERR "\t$filename\n"; + copy($filename, "$filename~") || print STDERR "\t\tWARN: could not create backup\n"; + if (open(T, $filename)) { + # slurp the file into a string + local $/; + $data = <T>; + $data =~ s/($SNIPPATHRE)\{([^}]+)\}/ + $map{$1} ? "$map{$1}$2\}" + : ((print STDERR "\t\tWARN: could not replace $1\n"), "$1\{$2}") + /oxge; + close T; + if (open(T, ">$filename")) { + print T $data; + close T; + } + else { + print STDERR "\t\tWARN: could not save replacement\n"; + } + } + else { + print STDERR "\t\tWARN: could not open file\n"; + } +} diff --git a/Master/texmf-dist/source/latex/stex/bin/filedate b/Master/texmf-dist/source/latex/stex/bin/filedate new file mode 100755 index 00000000000..8149b5e57bd --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/filedate @@ -0,0 +1,42 @@ +#!/usr/bin/perl -w +####################################################################################### +# A tool for updating .dtx files with a given package date. # +# Copyright (c) 2010, Deyan Ginev, released under the Gnu General Public License (GPL)# +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: https://svn.kwarc.info/repos/stex/trunk/bin/filedate$ # +####################################################################################### + +use strict; + +use Getopt::Long; +use Modparse; +use Pod::Usage; +use Cwd qw(abs_path); + +my ($file,$date) = @ARGV; +$file = abs_path($file); +open(IN,"<$file"); +my @lines = (); +while (<IN>) { + if ($_ =~ /\\Provides(Package|Class)/) { + $_ =~ s/\[(.*?)\s/\[$date /; + } + push @lines, $_; +} +close(IN); +open(OUT,">$file"); +print OUT join("",@lines); +close(OUT); + +__END__ + + +=head1 SYNOPSIS + +filedate <input filename> <newdate> + +Purpose: + Update the dates for a \ProvidePackage invocation in a given .dtx source + +Example: + filedate omdoc.dtx "2010/06/24" diff --git a/Master/texmf-dist/source/latex/stex/bin/gen-symdef-table.pl b/Master/texmf-dist/source/latex/stex/bin/gen-symdef-table.pl new file mode 100755 index 00000000000..cd6da0dc06a --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/gen-symdef-table.pl @@ -0,0 +1,85 @@ +#!/usr/bin/perl +use Cwd; + +die 'Set your environment variable "KWARC_HOME" and try again.' if !($ENV{KWARC_HOME}); + +open(PATH_STY,"$ENV{KWARC_HOME}/projects/stex/sty/paths.sty") || die "can't open path.sty"; +while ($line=<PATH_STY>) { + $line =~ m/\\def\\(\w*).*\/([\w-]*)\/#1/; + $macros{$2}=$1; # dir -> macro +} +close(PATH_STY); + +print <<PRE_TEX; +\\documentclass[notes]{mikoslides} +\\usepackage{amssymb} +\\usepackage{latexml,stex,program} +\\usepackage{ded,calbf,myindex} +\\usepackage{tikz,multicol} +\\usepackage{paths} +\\usepackage[show]{ed} +\\def\\bsp{\\sl\\color{green}} +\\def\\hrcr#1#2{#2} + +\\begin{document} +PRE_TEX + +chdir("$ENV{KWARC_HOME}/teaching/snippets/"); + +foreach $dir (<*/>) { + $dir = substr($dir,0,-1); + if (@ARGV){ # take all dirs listet in @ARGV + next if !(grep(/$dir/,@ARGV)) + } else { # take all dirs but those listed here + # next if $dir lt "b"; #test break + # next if $dir gt "comb"; #test break + next if grep(/$dir/,qw(PIC activemath admin eLearning lib kwarc mathweb mbase old.assignments omdoc openmath physml quantumcomputing sTex search semweb setthy spl1 term-indexing trs varia xml)); #skip these + next if grep(/$dir/,qw(ai codeml fa graphs-trees kr mws nlfrags pl0 pl1 prolog regexp)); #broken dirs + } + print "\\begin{omgroup}{$dir}\n"; + foreach $file (<${dir}/en/*.sms>) { + $file =~ m/([^\/]*).sms/; + $prefix = $1; + next if grep(/$prefix/,qw(all admin)); + print "\\begin{omgroup}{$prefix}\n"; + print "\\requiremodules[exclude]{\\$macros{$dir}\{en/$prefix}\}\n"; + open (FILE,"./$file") || die "can't open $file"; + while ($line=<FILE>) { + $line =~ s/%.*//; + if ($line =~ m/begin{module}/) { # many "begin{module}" in one line yields invalid stex!!! + $uses = ($line =~ m/id=([\w-]*)/) ? "[uses=$1]" : ""; + print "\\begin{module}$uses\n"; # symbols after inner modules yields stex errors!!! + print "\\begin{verbatim}\n"; + print "\\requiremodules[exclude]{\\$macros{$dir}\{en/$prefix}\}\n"; + print "\\begin{module}$uses\n"; + print "\\end{verbatim}\n"; +# print "\\begin{multicols}{2}\n"; + } + if ($line =~ m/\\symdef{([^}]*)}(?:\[(\d)\])?({\\assoc\[)?/) { + $symb = $1; + $arity = $2; + $isAssoc = $3 ne ""; + $defArity = $isAssoc ? 4 : $arity; + $exampleArity = $arity eq "" ? 0 : $defArity; + $arityOrAssoc = $isAssoc ? "assoc" : $arity; + $dummy_args = join("",map {"{$_}"} (qw(a b c d e f g h m)[0..$exampleArity-1])); + $dummy_args = "{a,b,c,d}" if $isAssoc; + $escaped_dummy_args = $dummy_args; + $escaped_dummy_args =~ s/{/\\{/g; + $escaped_dummy_args =~ s/}/\\}/g; +# print "{\\tt{$symb\[$arityOrAssoc\]}} $escaped_dummy_args\\hfill"; + print "{\\tt{$symb$escaped_dummy_args}} \\hfill "; + print "\$\\$symb$dummy_args\$\\\\\n"; + } + if ($line =~ m/end{module}/) { # several "end{mdoule}" allowed!!! +# print "\\end{multicols}\n"; + print $line; + } + } + close(FILE); + print "\\end{omgroup}\n"; + } + print "\\end{omgroup}\n"; +} + +print "\\end{document}"; diff --git a/Master/texmf-dist/source/latex/stex/bin/idcheck b/Master/texmf-dist/source/latex/stex/bin/idcheck new file mode 100755 index 00000000000..d832ac7788e --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/idcheck @@ -0,0 +1,29 @@ +#!/usr/bin/perl -w +use strict; + +use Getopt::Long; +use File::Path; +use Pod::Usage; +use TexId; + + + +my $tex = TexId->new(progress => 1); + + + +$tex->load_file_data('../GenCS/notes.tex'); + +my ($a, $b) = $tex->environments(); +print $b, "\n"; + +print $tex->snippath(), "\n"; + +$tex->parse('../GenCS/notes.tex'); +#print join(', ', $tex->use_env_list('omtext')), "\n"; + +#print $tex->edit_dist('anaIU', 'aanUI'), "\n"; + +$tex->check_uniq; +$tex->check_prefix; +$tex->apply_changes; diff --git a/Master/texmf-dist/source/latex/stex/bin/msplit b/Master/texmf-dist/source/latex/stex/bin/msplit new file mode 100755 index 00000000000..cf178ce9b5f --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/msplit @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w +############################################################################################## +# Program: msplit (a utility for splitting STeX documents along module boundaries) +############################################################################################## +# $URL: svn://kwarc.faculty.iu-bremen.de/kohlhase/kwarc/projects/content/bin/msplit$ +# $Rev: 3722 $; last modified by $Author: $ +# $Date: 2005-07-27 03:22:19 +0200 (Wed, 27 Jul 2005) $ +# Copyright (c) 2005 Ioan Sucan +############################################################################################## +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 [http://www.gnu.org/copyleft/gpl.html] +# for more details. +############################################################################################## +use strict; +use Getopt::Long; +use File::Path; +use Pod::Usage; + +my $input='-', my $output='-', my $path='', my $verbose=0, my $stop_at_end=0; +my $flag = "include"; +my $header='', my @hdr_data; + +sub texf { + my $fn = shift; + $fn.='.tex' if $fn !~ /\.tex$/; + return $fn; } + +sub write_file_data{ + my $filename = shift; + open(FS,$filename) or die "Cannot write $filename\n"; + print FS @_; + close(FS); } + +# remove the last component in a path +sub justpath{ + my $arg = shift; + return '' if ($arg !~ m!\/!); + while ($arg !~ m!\/$!) {chop($arg);} + return $arg; } +# end justpath + + +sub go { + my ($input, $output) = @_; + my $path = justpath($output); + + my @module_file=(); + my @out_data=(); + + print "Splitting $input...\n" if $verbose; + `mv $output $output~` if (-e $output); + $input="$input~" if ($input eq $output); + + open(FIN,$input) or die "Can't open $input\n"; + my $in_module=0; my $path_name; + foreach (<FIN>){ + chomp; + /([^%]*)((%.*)?)/; + ($_,my $comment)=($1,$2); + if (/\\begin\s*\{module\}/){ + $_ =~ s/\s//g; + /id=([\w-]*)/; + my $module_name = $1; + $path_name = "$path$module_name.tex"; + print "$path_name\n" if $verbose; + `mv $path_name $path_name~` if (-e $path_name); + push(@module_file,@hdr_data) if $header; + push(@module_file,"\n$_$comment\n"); + push(@out_data,"\\requiremodules[$flag]{$module_name}\n"); + $in_module=1; + next; } + if (/\\end\s*\{module\}/){ + $_ =~ s/\s//g; + push(@module_file,"$_$comment\n"); + mkpath(justpath($path_name)); + write_file_data(">$path_name",@module_file); + $in_module=0; + next; } + if ($stop_at_end && /\\end\s*\{document\}/){ + $_ =~ s/\s//g; + push(@out_data,"$_$comment\n"); + last; } + $_="$_$comment\n"; + if ($in_module) {push(@module_file,$_);} + else {push(@out_data,$_); }} + close(FIN); + mkpath($path) if $path; + write_file_data(">$output",@out_data); } + +GetOptions("output=s" => \$output, + "path=s" => \$path, + "header=s" => \$header, + "exclude" => sub { $flag = "exclude"; }, + "verbose" => sub { $verbose=1; }, + "stop" => sub { $stop_at_end=1; }, + "help" => sub { pod2usage(2)}); + +$input = $ARGV[0] if ($#ARGV>=0); +die "Input file does not exist\n" if (! defined $input || ! -e $input); +$output = $input if (! defined $output); + +if ($header && -e $header) { + open(HDR,$header); + @hdr_data = <HDR>; + close(HDR); } + +$path.='/' if $path && $path !~ m!\/$!; +go($input,$path.$output); +print "Done.\n" if $verbose; + +__END__ + + +=head1 SYNOPSIS + +msplit <inputfile> [options] + +Options: + + --output filename of new main .tex file; default: same as input + --path path where to generate the new documents; '.' by default + --header file to be copied at beginning of all new module files + --exclude modules exluded by default; if not mentioned, modules + are included by default + --verbose verbose on + --stop stop when \end{document} is found; default is to go on + --help this screen + + + + This program splits a .tex file into more files, each containing a module. + Example usage: + ./msplit slides.tex -o sl.tex -p ./modules -s diff --git a/Master/texmf-dist/source/latex/stex/bin/old/Makefile b/Master/texmf-dist/source/latex/stex/bin/old/Makefile new file mode 100644 index 00000000000..d2ae41c6401 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/old/Makefile @@ -0,0 +1,28 @@ +all: src exec + +src: idcheck.l defcon.l modstr.l + flex -ft idcheck.l > idcheck.yy.c + flex -ft defcon.l > defcon.yy.c + flex -f+t modstr.l > modstr.yy.cc + +idcheck: idcheck.l + flex -f $< + gcc lex.yy.c -lfl -o idcheck + +defcon: defcon.l + flex -f $< + gcc lex.yy.c -lfl -o defcon + +modstr: modstr.l + flex -f+ $< + g++ lex.yy.cc -lfl -o modstr + +exec: idcheck.yy.c defcon.yy.c modstr.yy.cc + gcc idcheck.yy.c -lfl -o idcheck + gcc defcon.yy.c -lfl -o defcon + g++ modstr.yy.cc -lfl -o modstr + +clean: + rm -f *.yy.c *.yy.cc *~ + +distclean: clean diff --git a/Master/texmf-dist/source/latex/stex/bin/old/defcon.l b/Master/texmf-dist/source/latex/stex/bin/old/defcon.l new file mode 100644 index 00000000000..ad758086145 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/old/defcon.l @@ -0,0 +1,91 @@ +%{ + +#include <string.h> + +char ltxml[100]; +char fext[6] = ".ltxml"; + +char symstr[200]; +char ltxmlstr[200]; + +int i,t,c,tmp,q; +FILE *lt; + +%} + +ID [a-zA-Z0-9._:\|-]* +NR [0-9]* + +%s idenv env sym + +%% + +"\\begin{module}"(" ")*"[" BEGIN(idenv); +<idenv>"]" BEGIN(INITIAL); + +<idenv>"id="{ID} { + for (i=3; i<yyleng; i++) ltxml[i-3]=yytext[i]; + t=yyleng-3; + tmp=strlen(fext); + for (i=0; i<tmp; i++) ltxml[t+i]=fext[i]; + t=t+tmp; + ltxml[t]=0; + if (!q) printf("File %s\n",ltxml); + lt = fopen(ltxml,"w"); + BEGIN(env); +} + +<env>"symdef{\\"{ID}"}"(.)* { +i=7; +while (yytext[i]!='}'){ + symstr[i-7]=yytext[i]; + i++; +} +symstr[i-7]=0; +BEGIN(sym); +} + +<sym>"latexmldef{"(.)* { +i=11; +while (i<yyleng){ + ltxmlstr[i-11]=yytext[i]; + i++; +} +ltxmlstr[i-12]=0; +fprintf(lt,"DefConstructor('\%s{}...{}','%s')\n",symstr,ltxmlstr); +BEGIN(env); +} + +<env,sym>"\\end{module}" { +fclose(lt); +BEGIN(INITIAL); +} + +\n c++; +. c++; + +%% + +main(argc, argv) + int argc; + char **argv; +{ + if (argc==1) { + printf("arguments expected: [-q] filename(s)\n"); + } else { + q=0; + i=1; + if (argv[1][0]=='-'){ + i++; + if (argv[1][1]=='q') q=1; + } + while (i<argc){ + if (!q) printf("Processing %s...\n",argv[i]); + yyin = fopen(argv[i], "r"); + c=0; + yylex(); + fclose(yyin); + i++; + } + } +} diff --git a/Master/texmf-dist/source/latex/stex/bin/old/idcheck.l b/Master/texmf-dist/source/latex/stex/bin/old/idcheck.l new file mode 100644 index 00000000000..9b1603527d2 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/old/idcheck.l @@ -0,0 +1,130 @@ +%{ +#include <string.h> +int ur,ok,a,lin,i,j,c,n,m,d,s,q,fe,f,for_ok,curr_lin; +typedef char idstr[50]; +idstr l[5000], r[5000]; +%} + +ID [a-zA-Z0-9._:\|-]* +WS [\n\t ]* + +%s env inenv fid foc + +%% + +"\\begin"{WS}"{"("proof"|"example")"}"{WS}"[" { +fe=1; +for_ok=0; +curr_lin=lin; +BEGIN(env); // stuff that "for" keyval is recommended for +} + +"\\begin"{WS}"{"("proof"|"example")"}" if (f) printf("Missing 'for' at line %d\n",lin); + +("\\begin"{WS}"{"("definition"|"assertion"|"proof"|"omtext"|"example"|"step"|"pfcase"|"module")"}"{WS}"[")|("\\justification"{WS}"[") { +fe=0; +BEGIN(env); +} + +<env>"]" { +if (fe && !for_ok && f) printf("Missing 'for' at line %d\n",curr_lin); +BEGIN(INITIAL); +} + +<env>"id"{WS}"="{WS} BEGIN(fid); + +<fid>{ID} { +for (i=0; i<yyleng; i++) l[n][i]=yytext[i]; +l[n][yyleng]=0; +if (s) printf("%s\n",l[n]); +n++; +BEGIN(env); +} + +<env>("for"){WS}"="{WS} { +for_ok=1; +BEGIN(foc); +} +<env>("continues"|"for"|"uses"|"premises"){WS}"="{WS} BEGIN(foc); + +<foc>{ID} { +for (j=0; j<yyleng; j++) r[m][j]=yytext[j]; +r[m][yyleng]=0; +m++; +BEGIN(env); +} + +<env>("premises"|"uses"){WS}"="{WS}"{" BEGIN(inenv); + +<inenv>{ID} { +strncpy(r[m],yytext,yyleng); +r[m][yyleng]=0; +m++; +} + +<inenv>"}" BEGIN(env); + +\n {c++;lin++;} +. c++; + +%% + +main(argc, argv) + int argc; + char **argv; +{ + if (argc==1) { + printf("Usage: idcheck [-q | -s | -f] filename(s)\n"); + printf("Option -s shows all detected IDs. \n"); + printf("Option -f shows line numbers for examples and proofs\n that have 'for' keyval missing. \n"); + printf("Option -q for quiet mode.\n"); + } else{ + s=0; q=0; + a=1; + if (argv[1][0]=='-') { + a++; + for (j=1; j<strlen(argv[1]); j++) + if (argv[1][j]=='s') s=1; else + if (argv[1][j]=='q') q=1; else + if (argv[1][j]=='f') f=1; + } + d=0; + while (a<argc){ + if (!q) printf("Parsing %s...\n",argv[a]); + yyin = fopen(argv[a] , "r"); + c = 0; + lin = 1; + n = 0; + m = 0; + yylex(); + fclose(yyin); + if (!q) printf("%d characters skipped. Found %d IDs. \n",c,n); + if (!q) printf("Checking for duplicates...\n"); + for (i=0; i<n; i++) + for (j=i+1; j<n; j++) + if (strcmp(l[i],l[j])==0) { + printf("ID=%s is a duplicate in %s\n",l[i],argv[a]); + d++; + } + if (!q) printf("Found %d duplicates.\n",d); + if (!q) printf("Checking references... (found %d)\n",m); + ur=0; + for (i=0;i<m; i++){ + ok=0; + for (j=0; j<n; j++) + if (strcmp(r[i],l[j])==0){ + ok=1; + break; + } + if (!ok) { + printf("Unmatched reference for ID=%s\n",r[i]); + ur++; + } + } + if (!q) printf("Found %d unmatched references.\n",ur); + a++; + } + return d+ur; + } + return 1; +} diff --git a/Master/texmf-dist/source/latex/stex/bin/old/modstr.l b/Master/texmf-dist/source/latex/stex/bin/old/modstr.l new file mode 100644 index 00000000000..ae0101147c5 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/old/modstr.l @@ -0,0 +1,137 @@ +%{ +#include <iostream> +#include <string> +#include <map> +#include <vector> +using namespace std; + + +const int indent = 4; +const char start_char = '*'; + +typedef struct { + vector<string> defs,list; + int father; +} nodetype; + +map<string,nodetype> g; + +string vertex, data; +int d, miss, skip; + +int max(int, int); + +%} + +ID [a-zA-Z0-9._:\|-]* +SEP [,;]* +WS [\n\t ]* +M [^}]* + +%x in_module found_vertex in_module_cont mdef +%x found_one_child found_more_children + +%% + +<INITIAL>"\\begin"{WS}"{module}"{WS}"[" BEGIN(in_module); + +<in_module>"id"{WS}"=" BEGIN(found_vertex); +<found_vertex>{ID} { +vertex = YYText(); +g[vertex].father=0; +if (miss) cout << endl << "<-------- Module '" << vertex + << "' -------->" << endl << endl; +BEGIN(in_module); +} +<in_module>"uses"{WS}"=" BEGIN(found_one_child); +<found_one_child>"{" BEGIN(found_more_children); +<found_more_children>"}" BEGIN(in_module); +<found_one_child>{ID} { +data=YYText(); +if (g[data].list.empty()) + g[vertex].father=g[data].father+1; +else + g[vertex].father=max(g[data].father+1,g[vertex].father); +g[data].list.push_back(vertex); +BEGIN(in_module); +} +<found_more_children>{ID} { +data=YYText(); +if (g[data].list.empty()) + g[vertex].father=g[data].father+1; +else + g[vertex].father=max(g[data].father+1,g[vertex].father); +g[data].list.push_back(vertex); +} + +<found_one_child,found_more_children,found_vertex>{SEP}|{WS} + +<in_module>"]" BEGIN(in_module_cont); + +<in_module,in_module_cont>(.|\n) + +<in_module_cont>"\\"("symdef"|"abbrdef"|"elldef"|"aliasdef"){WS}"{"{WS} BEGIN(mdef); +<mdef>{M} { +data = YYText(); +g[vertex].defs.push_back(data); +} +<mdef>"}" BEGIN(in_module_cont); +<in_module_cont>"\\end"{WS}"{module}" BEGIN(INITIAL); + +<INITIAL>(.|\n) if (miss) cout << YYText(); + +<*>{WS}(%)(.)*(\n)* + +%% + +void spc(int n){ + for(int i=0; i<n; i++) cout << " "; +} + +int max(int a, int b){ + return a>b?a:b; +} + +void go(map<string, nodetype > ::iterator node, int depth){ +if (skip && node->second.father!=depth) return; +spc(d); +cout << start_char << " " << node->first << "{"; +int tmp = node->second.defs.size()-1; +for (int j=0; j<=tmp; j++){ + cout << node->second.defs[j]; + if (j!=tmp) cout << ","; +} +cout << "}" << endl; +d+=indent; +for (int i=0; i<node->second.list.size(); i++) + go(g.find(node->second.list[i]),depth+1); +d-=indent; +} + +int main(int argc, char** argv){ +miss=0; +skip=0; +if (argc==2) + if (argv[1][0]=='-') + for (int z=1; argv[1][z]!=0; z++) + if (argv[1][z]=='m') miss=1; else + if (argv[1][z]=='s') skip=1; else + if (argv[1][z]=='h') { + cout << " Usage: modstr [-s|m|h]\n Input: stdin\n Output: stdout\n"; + cout << " Options: -s Show module usage only at the deepest level\n"; + cout << " -m Show text not within a module\n"; + cout << " -h This help screen\n"; + return 0; + } +if (miss) cout << "Text NOT within a module:\n" << endl; +FlexLexer* lex = new yyFlexLexer; +lex->yylex(); +d=0; +map<string, nodetype > ::iterator start = g.begin(); +map<string, nodetype > ::iterator stop = g.end(); +cout << endl; +for(;stop!=start;start++) + if (!start->second.father) go(start,0); +cout << endl; +return 0; +} diff --git a/Master/texmf-dist/source/latex/stex/bin/old/symdef b/Master/texmf-dist/source/latex/stex/bin/old/symdef new file mode 100755 index 00000000000..b5c789a1c72 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/old/symdef @@ -0,0 +1,46 @@ +#!/usr/bin/perl -w + +use strict; +use Getopt::Long; +use Pod::Usage; + +my $output = "-"; +my $input = "-"; + +GetOptions("output=s",\$output); + +$input = $ARGV[0] if @ARGV; + +open(FIN,$input) or die "Can't open input file."; +open(FOUT,">$output"); + +my $line; + +while ($line=<FIN>){ + if ($line !~ m/symdef/ && $line !~ m/elldef/ && $line !~ m/abbrdef/){ + print FOUT $line; + next; + } + if ($line =~ m/\}\[\d,/){ + print FOUT $line; + next; + } + + if ($line =~ m/\\(sym|abbr|ell)def\{\\([^\}]+)\}\[(\d)\]([^\n\%]+)(.*)/){ + print FOUT "\\$1def{\\$2}[$3,name=$2]$4$5\n"; + } else { + if ($line =~ m/\\(sym|ell|abbr)def\{\\([^\}]+)\}([^\n\%]+)(.*)/){ + print FOUT "\\$1def{\\$2}[0,name=$2]$3$4\n"; + } + } +} + +close(FIN); +close(FOUT); + + +__END__ + +=head1 SYNOPSIS + +symdef [--output=outputfile] [texfile] diff --git a/Master/texmf-dist/source/latex/stex/bin/rf b/Master/texmf-dist/source/latex/stex/bin/rf new file mode 100755 index 00000000000..7de36042620 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/rf @@ -0,0 +1,63 @@ +#!/usr/bin/perl -w + +####################################################################################### +# A tool for computing the module reuse factor for TEX files. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/rf$ # +# $Date: 2005-06-29 23:08:10 +0200 (Wed, 29 Jun 2005) $ $Rev: 3147 $ # +####################################################################################### + +use strict; +use Getopt::Long; +use Modparse; +use Pod::Usage; + +my $input = "-", my $verbose=0, my $stop_at_end=0; +my %arg_snippath; my @snippathList; + +GetOptions("path=s" => \%arg_snippath, + "defpath=s" => \@snippathList, + "verbose" => sub { $verbose=1; }, + "stop" => sub { $stop_at_end=1; }, + "help" => sub { pod2usage(2)}); + +$input = $ARGV[0] if ($#ARGV>=0); + +$main::lc1 = 0; $main::lc2 = 0; +my $mp = Modparse->new(snippathList=>\@snippathList, + snippath=>\%arg_snippath, + stopAtEnd=>$stop_at_end, + verbose=>$verbose, + onEveryLine=>sub { + $main::lc1++; + $main::lc2++ if $_[0]->{depth}==1; }); + +$mp->execute($input); +my $f = ($main::lc2>0)?$main::lc1/$main::lc2:0; +print "Reuse factor: $f\n"; + +__END__ + + +=head1 SYNOPSIS + +rf <input filename> [options] + + This program computes the reuse factor for a .tex document + + Options: + --path XXX specify the value of \XXX (some snippath) in case it is + = somePath not defined in the processed .tex file + --defpath XXX specify which \XXX (snippath definitions) to look for + --stop stop when \end{document} is found; default is to go on + --verbose verbose on + --help this screen + + + Example usage: + ./rf slides.tex -d snippath -v + + Interpretation: + compute the reuse factor for the file slides.tex, look for definitions + of \snippath, in verbose mode diff --git a/Master/texmf-dist/source/latex/stex/bin/rng2dot/ModelRNC.pm b/Master/texmf-dist/source/latex/stex/bin/rng2dot/ModelRNC.pm new file mode 100644 index 00000000000..53673e37dc8 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/rng2dot/ModelRNC.pm @@ -0,0 +1,770 @@ +# anything that starts with # is removed until \n (considered as a comment) +# except in literals; +# +# NCName is limited to a-zA-Z0-9.-_ +# +# no proper support for except nameClass +# no support for exceptPatterns + +package ModelRNC; + +use strict; +use File::Basename; + +my $DOCUMENT = '_Document_'; + +sub new{ + my ($class) = @_; + my $self = {}; + $self->{literalCount} = 0; + bless($self, $class); +} + +# this is the main method of the package +# it should be called right after new +sub process{ + my ($self, $filename) = @_; + $self->readfile($filename); + $self->clean_rnc; + $self->read_topLevel; + $self->build_info; + # free some memory + $self->{DATA} = ''; $self->{FILEPATH} = ''; $self->{GRAPH} = ''; +} + +sub Error{ + my ($self, $msg) = @_; + print "'$self->{DATA}'\n"; + die $msg."\n"; +} + +# read a file into $storage; +# or $self->{DATA} if $storage not given +sub readfile{ + my ($self, $filename, $storage) = @_; + + # NOTE: this is not exactly perfect + if ($self->{FILEPATH}){ + $filename = $self->{FILEPATH}.$filename unless -e $filename; } + my $basepath = dirname($filename); + $basepath .= '/' if ($basepath && $basepath !~ m|/$|); + $self->{FILEPATH} = $basepath; + + open(FIN, $filename) or $self->Error("Cout not open '$filename'"); + my @data = <FIN>; + close(FIN); + + # for use in namespace set selection + push(@{$self->{LOADEDFILES}}, $filename); + + if (defined $storage){ $$storage = join('',@data); } + else { $self->{DATA} = join('',@data); } +} + +# remove lines after ## +sub remove_annotations{ + my ($self, $data) = @_; + $data = \$self->{DATA} unless $data; + do {} while ($$data =~ s/\[[^\]\[]*\]//g); + $$data =~ s/\#\#[^\n]*//g; +} + +# remove all lines that start with # except +# the ones that start with ## +sub remove_comments{ + my ($self, $data) =@_; + $data = \$self->{DATA} unless $data; + $$data =~ s/\#[^\#\n][^\n]*//g; + $$data =~ s/\#\n/\n/g; +} + +sub scan_literals{ + my ($self, $data) = @_; + my @litseg; my $seg = 0; + $data = \$self->{DATA} unless $data; + while ($$data =~ s/\"\"\"((\"{0,2}[^\"])*)\"\"\"/_LITSEG$seg/) { $litseg[$seg++] = $1; } + while ($$data =~ s/\'\'\'((\'{0,2}[^\'])*)\'\'\'/_LITSEG$seg/) { $litseg[$seg++] = $1; } + while ($$data =~ s/\"([^\"\n]*)\"/_LITSEG$seg/) { $litseg[$seg++] = $1; } + while ($$data =~ s/\'([^\'\n]*)\'/_LITSEG$seg/) { $litseg[$seg++] = $1; } + + while ($$data =~ s/_LITSEG(\d+)\s*~\s*_LITSEG(\d+)/_LITSEG$seg/) + { $litseg[$seg++] = $litseg[$1].$litseg[$2]; } + + while ($$data =~ s/_LITSEG(\d+)/!LIT$self->{literalCount}/) + { $self->{literals}[$self->{literalCount}++] = $litseg[$1]; } +} + +# remove \x{N} sections +sub special_chars{ + my ($self, $data) = @_; + $data = \$self->{DATA} unless $data; + while ($$data =~ m/\\x\{([a-fA-F0-9x]+)\}/g){ + my $lng = length($&); my $p = pos($$data) - $lng; + substr($$data, $p, $lng) = chr(hex($1)); + pos($$data) = $p + 1; + } +} + +# remove redundant data from loaded file +sub clean_rnc{ + my ($self, $data) = @_; + $data = \$self->{DATA} unless $data; + $self->scan_literals($data); + $self->special_chars($data); + $self->remove_annotations($data); + $self->remove_comments($data); + # add a newline, just in case the last word is a keyword + # and for nice printing; + $$data.="\n"; +} + +# in the processing of the data, the data is destroyed +# provide two methods for resolving that +sub backup{ + my ($self) = @_; + $self->{BACKUP_DATA} = $self->{DATA}; +} + +sub restore{ + my ($self) = @_; + $self->{DATA} = $self->{BACKUP_DATA} if defined $self->{BACKUP_DATA}; +} + +# set or retrieve stored data +sub data{ + my ($self, $newdata) = @_; + if (defined $newdata){ $self->{DATA} = $newdata; } + else { return $self->{DATA}; } +} + +# put back some extracted string from DATA +sub put_back{ + my ($self, $back) = @_; + substr($self->{DATA}, 0, 0) = $back; +} + +# try to match a keyword; return 1 on success; 0 on failure +# NOTE: this implies that the used keywords should be followed by +# some non alphanumeric or space character +sub read_keyword{ + my ($self, $keyword) = @_; + return 0 if ($self->{DATA} !~ /^\s*\Q$keyword\E\s*[^a-zA-Z0-9_\-\.]/); + substr($self->{DATA}, 0, length($&)-1) = ''; + return 1; +} + +# same as read_keyword, except it dies not expect a non-word character +# after the word it searches +sub read_controlword{ + my ($self, $controlword) = @_; + return 0 if ($self->{DATA} !~ /^\s*\Q$controlword\E\s*/); + substr($self->{DATA},0,length($&)) = ''; + return 1; +} + +# expect a keyword; if the word is found, it is extracted +# otherwise, the program dies (the grammar is incorrect) +sub expect_keyword{ + my ($self, $keyword) = @_; + $self->Error("Expected keyword '$keyword' was not found") + if ($self->{DATA} !~ /^\s*\Q$keyword\E\s*/); + substr($self->{DATA}, 0, length($&)) = ''; +} + + +# Does not include Extender and CombiningChar +# (as in XML Namespaces: http://www.w3.org/TR/REC-xml/) +sub read_NCName{ + my ($self, $terminators) = @_; + my $termin_exists = 1; + if (defined $terminators) { $terminators = "[$terminators]"; } + else { $terminators = ''; $termin_exists = 0; } + if ($self->{DATA} =~ /^\s*([_a-zA-Z][_a-zA-Z0-9\.\-]*)\s*$terminators/){ + substr($self->{DATA}, 0, length($&)-$termin_exists) = ''; + return $1; + } + return undef; +} + +# try to match an identifierOrKeyword; return it in case +# of success; return undef in case of failure; +sub read_identifierOrKeyword{ + my ($self, $terminators) = @_; + $self->read_controlword('\\'); + return $self->read_NCName($terminators); +} + +# see if the argument is in the set of defined keyword of RelaxNG +sub isRNCKeyword{ + my ($word) = @_; + return ($word =~ /^\s*(attribute|default|datatypes|div|element|empty|external|grammar|include|inherit|list|mixed|namespace|notAllowed|parent|start|string|text|token)\s*$/); +} + +# read an identifier; return undef if no identifier can be read +sub read_identifier{ + my ($self, $terminators) = @_; + my $quote = $self->read_controlword('\\'); + my $ident = $self->read_NCName($terminators); + if (!$quote && $ident && isRNCKeyword($ident)){ + $self->put_back($ident); + return undef; + } + return $ident; +} + +# read a literal in any form given; +# segments are taken into account +sub read_literal{ + my ($self) = @_; + if ($self->{DATA} =~ /^\s*!LIT(\d+)\s*/){ + substr($self->{DATA}, 0, length($&)) = ''; + return $self->{literals}[$1]; + } + return undef; +} + +# read a namespace URI literal +sub read_namespaceURILiteral{ + my ($self, $inherited_namespace) = @_; + return $inherited_namespace if $self->read_keyword('inherit'); + return $self->read_literal; +} + +# read any URI literal +sub read_anyURILiteral{ + my ($self) = @_; + $self->read_literal; } + +sub getNS{ + my ($self, $nspref) = @_; + $self->{${$self->{LOADEDFILES}}[$#{$self->{LOADEDFILES}}]}->{NAMESPACE}{$nspref}; } + +sub setNS{ + my ($self, $nspref, $nsval) = @_; + $self->{${$self->{LOADEDFILES}}[$#{$self->{LOADEDFILES}}]}->{NAMESPACE}{$nspref} = $nsval; } + +# read all declarations, until none can be read +sub read_decl{ + my ($self, $inherited_namespace) = @_; + $inherited_namespace = '' unless defined $inherited_namespace; + $self->setNS('default',$inherited_namespace) unless $self->getNS('default'); + my $found = 1; + while ($found){ + if ($self->read_keyword('namespace')){ + my $namespace_name = $self->read_identifierOrKeyword('='); + $self->Error('Undefined namespace name') unless $namespace_name; + $self->expect_keyword('='); + my $namespace_value = + $self->read_namespaceURILiteral($inherited_namespace); + $self->Error('Undefined namespace URI') + unless defined $namespace_value; + $self->setNS($namespace_name, $namespace_value); + } + elsif ($self->read_keyword('default') && + $self->read_keyword('namespace')){ + my $namespace_name = undef; + if (!$self->read_controlword('=')){ + $namespace_name = $self->read_identifierOrKeyword('='); + $self->Error('Undefined namespace name') + unless $namespace_name; + $self->expect_keyword('='); + } + my $namespace_value = + $self->read_namespaceURILiteral($inherited_namespace); + $self->Error('Undefined namespace URI') + unless defined $namespace_value; + $self->setNS('default', $namespace_value); + $self->setNS($namespace_name, $namespace_value) + if $namespace_name; + } + elsif ($self->read_keyword('datatypes')){ + my $datatype_name = $self->read_identifierOrKeyword('='); + $self->Error('Undefined datatype name') unless $datatype_name; + $self->expect_keyword('='); + my $datatype_value = $self->read_literal; + $self->Error('Undefined datatype value') + unless defined $datatype_value; + } + else { $found = 0; } + } +} + +# ignore an annotation definition; +# (assumes annotation content does not exist) +# (it has been removed by clean_rnc) +sub ignore_annotation{ + my ($self) = @_; + $self->read_CName; } + +# read a name (CName) of the form NCName:NCName +sub read_CName{ + my ($self, $terminators) = @_; + $terminators = '\s' unless defined $terminators; + my $name = $self->read_NCName(':'); + if ($name){ + $self->expect_keyword(':'); + my $part2 = $self->read_NCName($terminators); + $self->Error('Incomplete CName definition') unless $part2; + $name .= ":$part2"; + } + return $name; +} + +# read a datatype name +sub read_datatypeName{ + my ($self, $terminators) = @_; + $terminators = '\s' unless defined $terminators; + if ($self->{DATA} =~ /^\s*string\s*[$terminators]/){ + substr($self->{DATA},0,length($&)-1) = ''; + return 'string'; + } + elsif ($self->{DATA} =~ /^\s*token\s*[$terminators]/){ + substr($self->{DATA},0,length($&)-1) = ''; + return 'token'; + } else { + return $self->read_CName($terminators); + } +} + +# read a datatype value +sub read_datatypeValue{ + my ($self) = @_; + return $self->read_literal; +} + +# return the set of names an element or an attribute can have +# this does not work well on complicated name classes +sub read_nameClassEx{ + my ($self, $terminators) = @_; + + my @result; + + if ($self->read_controlword('(')){ + @result = $self->read_nameClassEx($terminators.'\)'); + $self->expect_keyword(')'); + } else { + + #anyName + if ($self->read_controlword('*')){ + push(@result, '*'); + if ($self->read_controlword('-')){ + print STDERR "Warning: USE OF EXCEPT NAMECLASS NOT IMPLEMENTED\n"; + push(@result, $self->read_nameClassEx($terminators)); + } + } + # nsName or name(CName) + elsif (my $part1 = $self->read_NCName(':')){ + $self->expect_keyword(':'); + if ($self->read_controlword('*')){ + push(@result, "$part1:*"); + if ($self->read_controlword('-')){ + print STDERR + "Warning: USE OF EXCEPT NAMECLASS NOT IMPLEMENTED\n"; + push(@result, '-', + $self->read_nameClassEx($terminators)); + } + } else { + push(@result, $part1.':'.$self->read_NCName($terminators.'\|')); + } + } + # name(identifierOrKeyword) + else { + my $name = $self->read_identifierOrKeyword($terminators.'\|'); + $self->Error('Incomplete name class given') unless $name; + push(@result, $name); + } + } + + $self->Error('No name class provided') unless @result; + + # see if we have more possible names: + push(@result, $self->read_nameClassEx($terminators)) + if ($self->read_controlword('|')); + + return @result; +} + +sub read_nameClass{ + my ($self, $terminators, @parents) = @_; + $terminators = '\s' unless defined $terminators; + my @result = $self->read_nameClassEx($terminators); + my @finalRes; + + if (@parents && @result){ + + my @nsList, my %saw = (); + foreach (@parents){ + if (/\{(.*)\}:.+/){ + next if $saw{$1}; + push(@nsList, $1); $saw{$1} = 1; } + else { + next if $saw{'default'}; + push(@nsList, $self->getNS('default')); $saw{'default'} = 1; } + } + + foreach my $res(@result){ + if ($res =~ /(.+):(.+)/){ + push(@finalRes, $self->ns_prepend($2, $1)); } + else { + map(push(@finalRes, "{$_}:$res"), @nsList); } + } + } else { + map(push(@finalRes, (/(.+):(.+)/)? + $self->ns_prepend($2, $1):$self->ns_prepend($_)), @result); + } + return @finalRes; +} + + +# read a parameter declaration, if one exists +sub read_param{ + my ($self) = @_; + my $id = $self->read_identifierOrKeyword('='); + return (undef, undef) unless $id; + $self->expect_keyword('='); + my $val = $self->read_literal; + $self->Error('No parameter value specified') unless defined $val; + return ($id, $val); +} + +sub begin_read_newfile{ + my ($self) = @_; + my $file = $self->read_anyURILiteral; + my $inherit = 'default'; + if ($self->read_keyword('inherit')){ + $self->expect_keyword('='); + $inherit = $self->read_identifierOrKeyword; } + $inherit = $self->getNS($inherit); + my $newdata = ''; + $self->readfile($file, \$newdata); + $self->clean_rnc(\$newdata); + $self->put_back($newdata.'#'); + $self->read_decl($inherit); } + +sub end_read_newfile{ + my ($self) = @_; + pop(@{$self->{LOADEDFILES}}); + $self->expect_keyword('#'); } + +# read a pattern +sub read_pattern{ + my ($self, $grammarPath, $grammarIdent, @parentElements) = @_; + my $found = 1; my $grammarCount = 0; + my $DEF = $grammarPath.':'.$grammarIdent; + + if ($self->read_keyword('element')){ + my @elementNames = $self->read_nameClass('{', @parentElements); + $self->Error('Unspecified element name') unless @elementNames; + map(push(@{$self->{GRAPH}->{$DEF}->{$_}{ELEMENTS}}, + @elementNames), @parentElements); + $self->expect_keyword('{'); + $self->read_pattern($grammarPath, $grammarIdent, @elementNames); + $self->expect_keyword('}'); + } + elsif ($self->read_keyword('attribute')){ + my @attributeNames = $self->read_nameClass('{'); + $self->Error('Unspecified attribute name') unless @attributeNames; + map(push(@{$self->{GRAPH}->{$DEF}->{$_}{ATTRIBUTES}}, + @attributeNames), @parentElements); + $self->expect_keyword('{'); + $self->read_pattern($grammarPath, $grammarIdent, @parentElements); + $self->expect_keyword('}'); + } + elsif ($self->read_keyword('list') || $self->read_keyword('mixed')){ + $self->expect_keyword('{'); + $self->read_pattern($grammarPath, $grammarIdent, @parentElements); + $self->expect_keyword('}'); + } + elsif ($self->read_controlword('(')){ + $self->read_pattern($grammarPath, $grammarIdent, @parentElements); + $self->expect_keyword(')'); + } + elsif (my $datatypeValue = + $self->read_datatypeValue){ + # do nothing + } + elsif (my $datatypeName = + $self->read_datatypeName('\s\{\}\-!')){ + my $datatypeValue = $self->read_datatypeValue; + + # read parameters; ignore them for now + if ($self->read_controlword('{')){ + my ($ident, $val); + do{ + ($ident, $val) = $self->read_param; + } while ($ident && $val); + $self->expect_keyword('}'); + } + # read possible exceptPattern + if ($self->read_controlword('-')){ + print STDERR "Warning: USE OF EXCEPT PATTERN NOT IMPLEMENTED\n"; + $self->Error('exceptPattern expected but not found') + unless $self->read_pattern($grammarPath, $grammarIdent, + @parentElements); + } + } + elsif ($self->read_keyword('external')){ + $self->begin_read_newfile; + $self->read_pattern($grammarPath, $grammarIdent, @parentElements); + $self->end_read_newfile; + } + elsif ($self->read_keyword('grammar')){ + my $ident = $DEF.$grammarCount++; + $self->expect_keyword('{'); + $self->read_grammarContent($ident, @parentElements); + $ident .= ':start'; + map(push(@{$self->{GRAPH}->{$DEF}->{$_}{REFS}}, + $ident), @parentElements); + $self->expect_keyword('}'); + } + elsif ($self->read_keyword('parent')){ + my $ident = $self->read_identifier; + if ($grammarPath =~ /^([.]+:)[^:]+$/){ + $ident = $1.$ident; + map(push(@{$self->{GRAPH}->{$DEF}->{$_}{REFS}}, + $ident), @parentElements); + } + } + elsif ($self->read_keyword('empty') || $self->read_keyword('text') + || $self->read_keyword('notAllowed')){ + # do nothing + } + elsif (my $ident = $self->read_identifier){ + # check if we did not enter a grammar by mistake: + my $asg = $self->read_assignMethod(1); + if ($ident && $asg){ + $self->put_back($ident.$asg); + } else { + $ident = $grammarPath.':'.$ident; + map(push(@{$self->{GRAPH}->{$DEF}->{$_}{REFS}}, + $ident), @parentElements); + } + + } else { $found = 0; } + + if ($self->read_controlword('?') || $self->read_controlword('*') + || $self->read_controlword('+')){ + # ignore + } + + if ($self->read_controlword(',') || $self->read_controlword('|') + || $self->read_controlword('&')){ + Error('Pattern expected') unless + $self->read_pattern($grammarPath, $grammarIdent, @parentElements); + } + + return $found; +} + +sub read_assignMethod{ + my ($self, $asString) = @_; + if ($asString){ + return '&=' if ($self->read_controlword('&=')); + return '|=' if ($self->read_controlword('|=')); + return '=' if ($self->read_controlword('=')); + return undef; + } + return 3 if ($self->read_controlword('&=')); + return 2 if ($self->read_controlword('|=')); + return 1 if ($self->read_controlword('=')); + return 0; +} + +# read a grammar pattern +sub read_grammarPattern{ + my ($self, $DEF, @parentElements) = @_; + if ($self->read_keyword('grammar')){ + $self->expect_keyword('{'); + $self->read_grammarContent($DEF, @parentElements); + $self->expect_keyword('}'); } + else{ + $self->read_grammarContent($DEF, @parentElements);} +} + +# read all possible grammar contents +sub read_grammarContent{ + my ($self, $DEF, @parentElements) = @_; + my ($div, $found) = (0, 1); + + while ($found){ + if ($self->read_keyword('div')){ + $div++; + $self->expect_keyword('{'); + $self->read_grammarContent($DEF.':_G'.$div, @parentElements); + $self->expect_keyword('}'); + } + elsif ($self->read_keyword('include')){ + $self->begin_read_newfile; + $self->read_grammarPattern($DEF, @parentElements); + $self->end_read_newfile; + if ($self->read_controlword('{')){ + $self->read_grammarContent($DEF, @parentElements); + $self->expect_keyword('}'); } + } + elsif ($self->read_keyword('start')){ + my $asg = $self->read_assignMethod; + $self->Error('Invalid assign method') unless $asg; + @{$self->{GRAPH}->{$DEF.':start'}->{PARENTS}} = @parentElements; + $self->read_pattern($DEF, 'start', @parentElements); + } + elsif (my $ident = $self->read_identifier('=\|\&')){ + my $asg = $self->read_assignMethod; + $self->Error('Invalid assign method') unless $asg; + my $ref = $DEF.':'.$ident; + %{$self->{GRAPH}->{$ref}} = () if $asg == 1; + @{$self->{GRAPH}->{$ref}->{PARENTS}} = @parentElements; + $self->read_pattern($DEF, $ident, @parentElements); + } + elsif ($self->ignore_annotation) {} + else { $found = 0; } + } +} + +sub ns_prepend{ + my ($self, $tag, $ns_pref) = @_; + my $ns = $ns_pref?$self->getNS($ns_pref):undef; + $ns = $self->getNS('default') unless $ns; + return "{$ns}:$tag"; +} + +# this should match the whole file +sub read_topLevel{ + my ($self) = @_; + $self->read_decl; + $self->read_pattern($DOCUMENT, 'start', $DOCUMENT); + + my ($after, $before) = (0, 1); + while ($before != $after){ + $before = length($self->{DATA}); + $self->read_grammarContent($DOCUMENT, $DOCUMENT); + $after = length($self->{DATA}); + } + $self->{DATA} = trim($self->{DATA}); + $self->Error('Unable to completely process data') + unless $self->{DATA} eq ''; +} + +# remove leading and trailing white space +sub trim{ + my ($arg) = @_; + $arg =~ s/^\s+//; + $arg =~ s/\s+$//; + return $arg; +} + +sub build_info{ + my ($self) = @_; + + my %seen = (); + local *go = sub { + my ($reference, $node) = @_; + + my $ident = $reference.'#'.$node; + return if defined $seen{$ident}; + $seen{$ident} = 1; + + map($self->{ATTR}->{$node}{$_} = 1, + @{$self->{GRAPH}->{$reference}->{$node}{ATTRIBUTES}}) + if defined $self->{GRAPH}->{$reference}->{$node}{ATTRIBUTES}; + + my @sons; + map(push(@sons, ($reference, $_)), + @{$self->{GRAPH}->{$reference}->{$node}{ELEMENTS}}) + if defined $self->{GRAPH}->{$reference}->{$node}{ELEMENTS}; + + if (defined $self->{GRAPH}->{$reference}->{$node}{REFS}){ + my @refs = @{$self->{GRAPH}->{$reference}->{$node}{REFS}}; + foreach my $ref(@refs){ + next unless $self->{GRAPH}->{$ref}->{PARENTS}; + foreach my $son(@{$self->{GRAPH}->{$ref}->{PARENTS}}){ + map(push(@sons, ($ref, $_)), + @{$self->{GRAPH}->{$ref}->{$son}{ELEMENTS}}) + if defined $self->{GRAPH}->{$ref}->{$son}{ELEMENTS}; + push(@refs, @{$self->{GRAPH}->{$ref}->{$son}{REFS}}) + if defined $self->{GRAPH}->{$ref}->{$son}{REFS}; + # if a reference has attributes defined, + # they will appear as attributes to $DOCUMENT + # if the reference is not defined within some element + map($self->{ATTR}->{$node}{$_} = 1, + @{$self->{GRAPH}->{$ref}->{$son}{ATTRIBUTES}}) + if ($self->{GRAPH}->{$ref}->{$son}{ATTRIBUTES} && + ($son eq $DOCUMENT)); + } + } + } + my $sonCount = ($#sons+1)/2; + for (my $i = 0; $i < $sonCount; $i++){ + my ($ref, $son) = ($sons[2*$i], $sons[2*$i+1]); + go($sons[2*$i], $sons[2*$i+1]); + $self->{NODES}->{$node}{$son} = 1; + } + }; + + go($DOCUMENT.':start', $DOCUMENT); + + %seen = (); + local *gnodes = sub { + my ($node) = @_; + return if $seen{$node}; + $seen{$node} = 1; + foreach my $son(keys %{$self->{NODES}->{$node}}){ + map($self->{GNODES}->{$node}{$_} = $son, + keys %{$self->{NODES}->{$son}}); + gnodes($son); } + }; + + gnodes($DOCUMENT); + @{$self->{TAGLIST}} = keys %seen; +} + +sub getTagList { + my ($self) = @_; + return @{$self->{TAGLIST}}; +} + +sub tagChildren { + my ($self, $tag) = @_; + keys %{$self->{NODES}->{$tag}}; } + +# given a tag and a childtag, return whether +# tag can contain childtag +sub canContain() +{ + my ($self, $tag, $childtag) = @_; + return ($self->{NODES}->{$tag}{$childtag} || + $self->{NODES}->{$tag}{'*'})?1:0; +} + +# there can be more results: list ? +# there can be no result, but a class of results.. like a nsName +# choose representative? +sub canContainIndirect() +{ + my ($self, $tag, $childtag) = @_; + return $self->{GNODES}->{$tag}{$childtag} if + $self->{GNODES}->{$tag}{$childtag}; + + if ($self->{NODES}->{$tag}{'*'}){ + foreach (@{$self->{TAGLIST}}){ + return $_ if $self->{NODES}->{$_}{$childtag}; + } + } +} + +# given a tag and an attribute return whether +# the tag can have that attribute +sub canHaveAttribute() +{ + my ($self, $tag, $attr) = @_; + return ($self->{ATTR}->{$tag}{$attr} || + $self->{ATTR}->{$tag}{'*'})?1:0; +} + +sub canContainSomehow() +{ + my ($self, $tag, $childtag) = @_; + return ($self->canContain($tag, $childtag) || + $self->canContainIndirect($tag, $childtag)); +} + +1; diff --git a/Master/texmf-dist/source/latex/stex/bin/rng2dot/rng2dot b/Master/texmf-dist/source/latex/stex/bin/rng2dot/rng2dot new file mode 100755 index 00000000000..588b8827c63 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/rng2dot/rng2dot @@ -0,0 +1,37 @@ +#!/usr/bin/perl -w + +use ModelRNC; + +die "No input file\n" unless $ARGV[0]; +my $opt = $ARGV[1] || ''; + +my $rnc = ModelRNC->new(); +$rnc->process($ARGV[0]); +print STDERR 'Unable to properly parse ('.$rnc->data.")\n" if $rnc->data; + +my %seen = (); +sub make_graph { + my ($node) = @_; + my @children = $rnc->tagChildren($node); + my $pnode = $node; + $pnode =~ s/^\{[^\}]*\}://; $pnode =~ s/\-|\+|\*|\s/_/g; + my @pchildren = @children; + for (my $i = 0 ; $i < @pchildren; $i++) { + $pchildren[$i] =~ s/^\{[^\}]*\}://; + $pchildren[$i] =~ s/\-|\+|\*|\s/_/g; } + if ($opt eq 'txt') { + print "$pnode: ".join(', ', @pchildren)."\n\n"; } + else { + for (my $i = 0 ; $i < @pchildren; $i++) { + print "$pnode -> ".$pchildren[$i].";\n"; }} + return 0 if $seen{$node}; + $seen{$node} = 1; + foreach my $child(@children) { + make_graph($child); } + 1; } + +print "digraph RNC {\n" unless $opt eq 'txt'; +make_graph('_Document_'); +print "}\n" unless $opt eq 'txt'; + +__END__ diff --git a/Master/texmf-dist/source/latex/stex/bin/sgraph b/Master/texmf-dist/source/latex/stex/bin/sgraph new file mode 100755 index 00000000000..c4e709db476 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/sgraph @@ -0,0 +1,173 @@ +#!/usr/bin/perl -w +####################################################################################### +# A tool for creating graphs of module usage patterns based on graphviz. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/sgraph$ # +# $Date: 2005-10-04 19:31:43 +0200 (Tue, 04 Oct 2005) $ $Rev: 4376 $ # +####################################################################################### + +use strict; + +use Getopt::Long; +use Modparse; +use Pod::Usage; + +my $input = "-", my $output = "out", my $format = "ps"; +my $root, my $stop_at_end=0, my $use_grouping = 0; +my $rmdot = 0, my $verbose=0, my $theory = '', my $srange = ''; +my %arg_snippath; my @snippathList; + +sub group_name{ + my ($st) = @_; + if ($st =~ /^(.*[\/\\])?([^\/\\]+)\.[^\.\/\\]*$/) { $st = $2; } + elsif ($st =~ /^(.*[\/\\])?([^\.\/\\]+)$/) { $st = $2; } + $st =~ s/-/_/g; + return $st; } + +GetOptions("output=s" => \$output, + "format=s" => \$format, + "nodot" => sub {$rmdot = 1;}, + "root=s" => \$root, + "theory=s" => \$theory, + "sliderange=s" => \$srange, + "path=s" => \%arg_snippath, + "defpath=s" => \@snippathList, + "verbose" => sub {$verbose = 1;}, + "grouping" => sub {$use_grouping = 1}, + "stop" => sub {$stop_at_end = 1}, + "help" => sub {pod2usage(2)}); + +$output = $1 if ($output =~ m/([^.]+)\..*/); +$input = $ARGV[0] if ($#ARGV>=0); +$root = group_name($input) unless $root; + + +my %data = (); my %group = (); +my $mp = Modparse->new(snippathList=>\@snippathList, + snippath=>\%arg_snippath, + stopAtEnd=>$stop_at_end, + verbose=>$verbose, + onBegin=>sub { $_[0]->{perm}->{slide} = 0; $_[0]->{perm}->{linecount} = 0; + if ($srange =~ /(\d+)\:(\d+)/){ + ($_[0]->{perm}->{sbegin}, $_[0]->{perm}->{send}) = ($1, $2); + $_[0]->{perm}->{in_sliderange} = ($_[0]->{perm}->{sbegin}<1); + } else { $_[0]->{perm}->{in_sliderange} = 1; }}, + onBeginFile=>sub { $_[0]->{grp} = group_name($_[0]->{filename}); }, + onBeginModule=>sub { + if ($_[0]->{perm}->{in_sliderange} && (my $id = $_[0]->{module_id})){ + $id =~ s/[:-]/_/g; + my $uses = ''; + if ($_[0]->{module_args} =~ /uses=(([\w-]+)|(\{[\w,-]+\}))/){ + $uses = $1; + $uses =~ s/,/;/g; $uses =~ s/[:-]/_/g; } + $data{$id}=$uses; + $group{$id}=$_[0]->{perm}->{grp}; + }}, + onEveryLine=>sub { + $_[0]->{perm}->{linecount}++; + print ". " if ($_[0]->{pack}->{verbose} && ($_[0]->{perm}->{linecount} % 1000==0)); + $_[0]->{perm}->{slide}++ if $_[0]->{simple_tex} =~ /\\begin\{slide\}/; + $_[0]->{perm}->{in_sliderange}=($_[0]->{perm}->{slide}<=$_[0]->{perm}->{send} && + $_[0]->{perm}->{slide}>=$_[0]->{perm}->{sbegin}) + if ($_[0]->{perm}->{sbegin} && $_[0]->{perm}->{send}); + }); + +print "\nGenerating graph...\n" if $verbose; + +$mp->execute($input); + +my @queue=(); + +if ($theory){ + $theory =~ s/-/_/g; + if ($data{$theory}){ + my $start = 0, my $end = 1, my %already_in; + $queue[0] = $theory; + $already_in{$theory} = 1; + while ($start<$end){ + my $idx, my $usesx; + $idx = $queue[$start]; + $usesx = $data{$queue[$start]}; + $start++; + if ($usesx){ + $usesx =~ s/\{//; + $usesx =~ s/\}//; + foreach (split(/;/,$usesx)){ + next if $already_in{$_}; + $queue[$end] = $_; + $already_in{$_} = 1; + $end++; + } + } + } + } +} else{ + @queue = keys %data; +} + +open(FOUT,">$output.dot") or die "Can't open output file\n"; +print FOUT "digraph TEX {\n"; +print FOUT "$root [shape=box];\n"; + +if ($use_grouping){ + my %subgraph = (); + foreach (@queue){ + $subgraph{$group{$_}}.="$_;"; + } + foreach my $subgr (keys %subgraph){ + print FOUT "subgraph cluster_$subgr {\n"; + print FOUT "color = blue;\n"; + print FOUT "label = $subgr;\n"; + print FOUT "$subgraph{$subgr}\n"; + print FOUT "}\n"; + } +} + +my $lk = 0; +for my $idx (@queue){ + my $usesx = $data{$idx}; + $lk=$lk+($usesx =~ tr/;//)+1; + if ($usesx){ + print FOUT "$idx -> $usesx;\n"; + } else { + print FOUT "$idx -> $root;\n"; + } +} + +print "Number of links: $lk\n" if $verbose; + + +print FOUT "}\n"; +close(FOUT); + +`dot -T$format -o $output.$format $output.dot`; +unlink "$output.dot" if ($rmdot==1); + +print "Done.\n" if $verbose; + +__END__ + +=head1 SYNOPSIS + +sgraph <filename> [options] + + <filename> .tex input file; stdin by default + + Options: + --output output file; out.dot by default + --format output format; .ps by default; for available formats, see dot --help + --nodot do not generate .dot file, just target format + --root the 'root' of the graph. (name of course) + --theory generate a subgraph for the theory + --sliderange only look at the given slide range; (2:16 for example) + --path XXX specify the value of \XXX (some snippath) in case it is + = somePath not defined in the processed .tex file + --defpath XXX specify which \XXX (snippath definitions) to look for + --stop stop reading data when \end{document} is found, not at EOF + --grouping group modules within sections. + --verbose verbose on + --help this screen + +Example: +./sgraph slides.tex -o graph -f ps -n -t TCN --sliderange 20:10000 -r GenCS -v diff --git a/Master/texmf-dist/source/latex/stex/bin/sms b/Master/texmf-dist/source/latex/stex/bin/sms new file mode 100755 index 00000000000..4599f3e2763 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/sms @@ -0,0 +1,135 @@ +#!/usr/bin/perl -w +####################################################################################### +# A tool for creating STeX Module Signatures (SMS) files. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/sms$ # +# $Date: 2006-10-22 20:01:47 +0200 (Sun, 22 Oct 2006) $ $Rev: 10669 $ # +####################################################################################### + +use strict; + +use Getopt::Long; +use Modparse; +use Pod::Usage; + +my $input = "-", my $verbose=0, my $stop_at_end=0; +my %arg_snippath; my @snippathList; + +# match {,} brackets that are not comments or special characters +sub match{ + my $data = shift; + my $b = 0, my $i = 0, my $ignore = 0 ; + foreach (split('',$data)){ + $i++; + if ($ignore == 1){ + $ignore = 0; + next; + } + if ($ignore == 2){ + next if $_ ne "\n"; + $ignore = 0; + next; + } + if ($_ eq "\\"){ + $ignore = 1; + next; + } + if ($_ eq '%'){ + $ignore = 2; + next; + } + $b++ if $_ eq '{'; + $b-- if $_ eq '}'; + return (substr($data,0,$i),substr($data,$i,length($data)-$i+1)) if !$b; + } + return ('',$data); +} + + +####### start of program ####### + +GetOptions("verbose" => sub { $verbose=1; }, + "stop" => sub { $stop_at_end=1; }, + "path=s" => \%arg_snippath, + "defpath=s" => \@snippathList, + "help" => sub { pod2usage(2)}); + +$input = $ARGV[0] if ($#ARGV>=0); + +my $mp = Modparse->new(snippathList=>\@snippathList, + snippath=>\%arg_snippath, + stopAtEnd=>$stop_at_end, + verbose=>$verbose, + recursion=>0, + onBeginFile=>sub { @{$_[0]->{'sms'.$_[0]->{depth}}}=(); }, + onBeginModule=>sub { push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}); + @{$_[0]->{'sms'.$_[0]->{depth}}}[-1] =~ s/\n$/%\n/; }, + onEndModule=>sub { push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}); + @{$_[0]->{'sms'.$_[0]->{depth}}}[-1] =~ s/\n$/%\n/ }, + onRecurse=>sub { + my $recurse = $_[0]->{original}; + $recurse =~ s/include/exclude/g; + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $recurse); }, + onEndFile=>sub { + my $file = $_[0]->{pack}->new_ext($_[0]->{filename},'.sms'); + open(FOUT, ">$file") or die "Cannot write $file\n"; + print FOUT @{$_[0]->{'sms'.$_[0]->{depth}}}; + close(FOUT); + `touch $file` unless @{$_[0]->{'sms'.$_[0]->{depth}}}; + print "Wrote $file\n" if $verbose; }, + onEveryLine=>sub { + my @lines = @{$_[0]->{'sms'.$_[0]->{depth}}}; + if ($_[0]->{in_module}){ + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}) + if ($_[0]->{simple_tex} =~ /\\(sym|abbr|ell)def\{([^\}]+)\}/ || + $_[0]->{simple_tex} =~ /\\symdef\[([^\]]+)\]/); + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}) + if ($_[0]->{simple_tex} =~ /\\importmodule/); + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}) + if ($_[0]->{simple_tex} =~ /\\importOMDocmodule/); + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}) + if ($_[0]->{simple_tex} =~ /\\requiremodules/); + push(@{$_[0]->{'sms'.$_[0]->{depth}}}, $_[0]->{original}) + if ($_[0]->{simple_tex} =~ /\\requirepackage/); + if ((/\\STRlabel\{([^\}]+)\}(\{.*)/) || (/\\STRsemantics\[([^\]]+)\](\{.*)/)){ + my ($label, $line) = ($1, "$2 $_[0]->{comment}"); + my ($matched, $rest) = (undef, undef); + while (1) { + ($matched, $rest) = match($line); + last if $matched; + $line.=$_[0]->{nextline}(); } + $_[0]->{rewriteline}($rest) if $rest; + $line = "\\STRlabeldef{$label}$matched"; chomp($line); + map(push(@{$_[0]->{'sms'.$_[0]->{depth}}},"$_\n"),split("\n",$line)); + } + @{$_[0]->{'sms'.$_[0]->{depth}}}[-1] =~ s/\n$/%\n/ + if (@lines < @{$_[0]->{'sms'.$_[0]->{depth}}}); + }} ); + +$mp->execute($input); + +print "Done.\n" if $verbose; + + +__END__ + + +=head1 SYNOPSIS + +sms <input filename> [options] + +Options: + + --verbose verbose on + --stop stop when \end{document} is found; default is to go on + --path XXX=somePath specify the value of \XXX (some snippath) in case it is + not defined in the processed .tex file + --defpath XXX specify which \XXX (snippath definitions) to look for + --help this screen + +Purpose: + Generate .sms files (STeX Module Signatures) from .tex files + +Example: + sms slides.tex -v diff --git a/Master/texmf-dist/source/latex/stex/bin/termin b/Master/texmf-dist/source/latex/stex/bin/termin new file mode 100755 index 00000000000..0589be09c2f --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/bin/termin @@ -0,0 +1,279 @@ +#!/usr/bin/perl -w + +####################################################################################### +# A tool for automatized replacement of plain words with their \termin macros. # +# Copyright (c) 2005, Ioan Sucan, released under the Gnu General Public License (GPL) # +# see http://www.gnu.org/copyleft/gpl.html # +# $URL: svn://kwarc.eecs.iu-bremen.de/repos/kwarc/projects/content/bin/termin$ # +# $Date: 2005-10-04 17:47:41 +0200 (Tue, 04 Oct 2005) $ $Rev: 4371 $ # +####################################################################################### + +use strict; + +use Getopt::Long; +use Term::ANSIColor; +use Pod::Usage; + +my $verbose = 0; +my $wordDefs={}, my $twinDefs={}, my $atwinDefs={}; + +use constant twin => 'T'; +use constant word => 'W'; +use constant atwin => 'A'; + +my $before_chars = 128; +my $after_chars = 128; + +sub loadDefs{ + my ($tex_file) = @_; + + # read file + open(FIN, $tex_file) or die "Cannot read $tex_file\n"; + my @contentLines = <FIN>; + close(FIN); + + my $content = join('',@contentLines); + $content =~ s/\s+//g; + $content =~ s/%[^\n]*\n//g; + pos($content) = 0; + + my %modules = (); + while ($content =~ m/\\begin\{module\}\[([^\]]+)\]/g){ + next unless $1 =~ /id=([^\],]+)/; + $modules{pos($content)} = $1; + } + my @posList = keys %modules; + my $modIndex, my $current_module; + + # see definiens of form \definiens[bar]{foobar} + # word 'foobar', concept 'bar', within module 'foo' + pos($content) = 0; $modIndex = 0; $current_module = $modules{$posList[0]}; + while ($content =~ m/\\definiens\[([^\]\-]+)\]\{([^\}]+)\}/g){ + my $p = pos($content); + while ($modIndex < $#posList && $p > $posList[$modIndex+1]) { + $modIndex++; $current_module = $modules{$posList[$modIndex]}; } + push(@{$wordDefs->{modules}}, $current_module); + push(@{$wordDefs->{concepts}}, $1); + push(@{$wordDefs->{words}}, $2); + print word, " ==> $current_module: $1: $2\n" if $verbose>=2; + } + + # see definiens of form \definiens[aaa-bbb]{\twin{ccc}{ddd}} + # words 'ccc ddd', concept 'aaa-bbb', within module 'foo' + pos($content) = 0; $modIndex = 0; $current_module = $modules{$posList[0]}; + while ($content =~ m/\\definiens\[([^\-\]]+)\-([^\]]+)\]\{\\twin\{([^\}]+)\}\{([^\}]+)\}\}/g){ + my $p = pos($content); + while ($modIndex < $#posList && $p > $posList[$modIndex+1]) { + $modIndex++; $current_module = $modules{$posList[$modIndex]}; } + push(@{$twinDefs->{modules}}, $current_module); + push(@{$twinDefs->{concepts}}, "$1-$2"); + push(@{$twinDefs->{words}}, $3); + push(@{$twinDefs->{twins}}, $4); + print twin, " ==> $current_module: $1-$2: $3 $4\n" if $verbose>=2; + } + + # \twindef{aaa}{bbb} + pos($content) = 0; $modIndex = 0; $current_module = $modules{$posList[0]}; + while ($content =~ m/\\twindef\{([^\}]+)\}\{([^\}]+)\}/g){ + my $p = pos($content); + while ($modIndex < $#posList && $p > $posList[$modIndex+1]) { + $modIndex++; $current_module = $modules{$posList[$modIndex]}; } + push(@{$twinDefs->{modules}}, $current_module); + push(@{$twinDefs->{concepts}}, "$1-$2"); + push(@{$twinDefs->{words}}, $1); + push(@{$twinDefs->{twins}}, $2); + print twin, " ==> $current_module: $1-$2: $1 $2\n" if $verbose>=2; + } + + # see definiens of form \definiens[aaa-bbb-ccc]{\twin{ddd}{eee}{fff}} + # words 'ddd eee fff', concept 'aaa-bbb-ccc', within module 'foo' + pos($content) = 0; $modIndex = 0; $current_module = $modules{$posList[0]}; + while ($content =~ m/\\definiens\[([^\-\]]+)\-([^\-\]]+)\-([^\]]+)\]\{\\atwin\{([^\}]+)\}\{([^\}]+)\}\{([^\}]+)\}\}/g){ + my $p = pos($content); + while ($modIndex < $#posList && $p > $posList[$modIndex+1]) { + $modIndex++; $current_module = $modules{$posList[$modIndex]}; } + push(@{$atwinDefs->{modules}}, $current_module); + push(@{$atwinDefs->{concepts}}, "$1-$2-$3"); + push(@{$atwinDefs->{words}}, $4); + push(@{$atwinDefs->{twins}}, $5); + push(@{$atwinDefs->{adjs}}, $6); + print atwin, " ==> $current_module: $1-$2-$3: $4 $5 $6\n" if $verbose>=2; + } + + # \atwindef{aaa}{bbb}{ccc} + pos($content) = 0; $modIndex = 0; $current_module = $modules{$posList[0]}; + while ($content =~ m/\\atwindef\{([^\}]+)\}\{([^\}]+)\}\{([^\}]+)\}/g){ + my $p = pos($content); + while ($modIndex < $#posList && $p > $posList[$modIndex+1]) { + $modIndex++; $current_module = $modules{$posList[$modIndex]}; } + push(@{$atwinDefs->{modules}}, $current_module); + push(@{$atwinDefs->{concepts}}, "$1-$2-$3"); + push(@{$atwinDefs->{words}}, $1); + push(@{$atwinDefs->{twins}}, $2); + push(@{$atwinDefs->{adjs}}, $3); + print atwin, " ==> $current_module: $1-$2-$3: $1 $2 $3\n" if $verbose>=2; + } + +} + +sub max{ + my ($max, @values) = @_; + foreach (@values) { $max = $_ if $_ gt $max;} + return $max; +} + +sub nospace{ + my ($str) = @_; + $str =~ s/\s+/ /g; + $str =~ s/^\s//; + $str =~ s/\s$//; + return $str; +} + +sub replaceDefs{ + my ($in_tex_file, $out_tex_file) = @_; + + open(FIN, $in_tex_file) or die "Cannot read $in_tex_file\n"; + my @content_lines = <FIN>; + close(FIN); + + my $content = join('',@content_lines); + my $lcont = length($content); + + local *go_word = sub { + + my ($word, $new_word1_ex, $new_word2_ex) = @_; + $new_word2_ex = $new_word1_ex unless defined $new_word2_ex; + + while ($content =~ m/([^\{\s]?)(\s*$word\s*)[^\}\s]?/gi){ + my $p = pos($content); + my $ahead_len = length($1); my $matched_word = $2; + my $wlen = length($matched_word); + my $trail_len = length($&) - $wlen - $ahead_len; + + if (($ahead_len != 0 || $trail_len != 0) || + ($ahead_len == 0 && $trail_len == 0 && ($p == $wlen || $p == $lcont))){ + my $start_pos = max(0, $p - $wlen - $trail_len - $before_chars); + my $new_word1 = $new_word1_ex; my $new_word2 = $new_word2_ex; + + my $word_count = 0; + while ($matched_word =~ /\s*([^\s]+)\s*/g){ + my $replace = $1; + $new_word1 =~ s/W%$word_count/$replace/g; + $new_word2 =~ s/W%$word_count/$replace/g; + $word_count++; + } + + print "\nAnnotate '"; + print color 'bold blue'; print nospace($matched_word); print color 'reset'; + print "' with \n Y = '"; print color 'red bold'; print $new_word2; + print color 'reset'; print "'\n y = '"; print color 'red bold'; + print $new_word1; print color 'reset'; print "'\n in: \n<<< "; + print color 'green'; + print substr($content, $start_pos, $before_chars); + print color 'bold blue'; + print substr($content, $start_pos + $before_chars, $wlen); + print color 'reset green'; + print substr($content, $start_pos + $before_chars + $wlen, $after_chars); + print color 'reset'; + print " >>> ?\n"; + print "Options: <Y, y, [n]> "; + + my $answer = <STDIN>; + chomp($answer); + + if ($answer eq 'y'){ + substr($content, $p - $wlen - $trail_len, $wlen) = $new_word1; + $lcont = length($content); + pos($content) = $p + length($new_word1) - $wlen; + print "PROGRESS: Matched text was replaced with '$new_word1'\n" if $verbose; + } elsif ($answer eq 'Y'){ + substr($content, $p - $wlen - $trail_len, $wlen) = $new_word2; + $lcont = length($content); + pos($content) = $p + length($new_word2) - $wlen; + print "PROGRESS: Matched text was replaced with '$new_word2'\n" if $verbose; + } + + } + pos($content) = $p - $trail_len; + } + }; + + my $we = "(s|(ing))?"; # word endings + if (defined $wordDefs->{words}){ + my $wordDefsCount = $#{$wordDefs->{words}} + 1; + for (my $j = 0 ; $j < $wordDefsCount; $j++){ + my $word = "${$wordDefs->{words}}[$j]$we"; + my $new_word = " {\\termin[cd=${$wordDefs->{modules}}[$j],name=${$wordDefs->{concepts}}[$j]]". + "{W%0} "; + go_word($word, $new_word); + } + } + + if (defined $twinDefs->{words}){ + my $twinDefsCount = $#{$twinDefs->{words}} + 1; + for (my $j = 0 ; $j < $twinDefsCount; $j++){ + my $word = "${$twinDefs->{words}}[$j]$we\\s+${$twinDefs->{twins}}[$j]$we"; + my $new_word1 = " {\\termin[cd=${$twinDefs->{modules}}[$j],name=${$twinDefs->{concepts}}[$j]]". + "{W%0 W%1}} "; + my $new_word2 = " {\\termin[cd=${$twinDefs->{modules}}[$j],name=${$twinDefs->{concepts}}[$j]]". + "{\\twin{W%0}{W%1}}} "; + go_word($word, $new_word1, $new_word2); + } + } + + if (defined $atwinDefs->{words}){ + my $atwinDefsCount = $#{$atwinDefs->{words}} + 1; + for (my $j = 0 ; $j < $atwinDefsCount; $j++){ + my $word = "${$atwinDefs->{words}}[$j]$we\\s+${$atwinDefs->{twins}}[$j]$we\\s+${$atwinDefs->{adjs}}[$j]$we"; + my $new_word1 = " {\\termin[cd=${$atwinDefs->{modules}}[$j],name=${$atwinDefs->{concepts}}[$j]]". + "{W%0 W%1 W%2}} "; + my $new_word2 = " {\\termin[cd=${$atwinDefs->{modules}}[$j],name=${$atwinDefs->{concepts}}[$j]]". + "{\\atwin{W%0}{W%1}{W%2}}} "; + go_word($word, $new_word1, $new_word2); + } + } + + open(FOUT, ">$out_tex_file") or die "Cannot write $out_tex_file\n"; + print FOUT $content; + close(FOUT); + +} + +my @background, my @main, my @output; + +GetOptions("verbose" => sub {$verbose++;}, + "background=s" => \@background, + "main=s" => \@main, + "output=s" => \@output, + "help" => sub { pod2usage(2)}); + +foreach (@background) { loadDefs($_); } + +for (my $i = 0 ; $i <= $#main; $i++) { + replaceDefs($main[$i], $output[$i] || $main[$i]); +} + + +__END__ + +=head1 SYNOPSIS + +termin [options] + +Options: + + --verbose verbose on + --background background file to read \termin{} definitions from + --main main file to process + --output output file; the modified content of the main file will + be written here + --help this screen + +Purpose: + Read the \termin definitions from a background file and update a specific main file; + output will be written to the specified the output file. + Note: multiple background/main/output files may be specified. + +Example: + termin --background a.tex --background b.tex --main slides.tex --output new_slides.tex |