#! /usr/bin/perl -w # Determine the path to the McStas system directory. This must be done # in the BEGIN block so that it can be used in a "use lib" statement # afterwards. use Config; use Cwd; BEGIN { # default configuration (for all high level perl scripts) if($ENV{"MCSTAS"}) { $MCSTAS::sys_dir = $ENV{"MCSTAS"}; } else { if ($Config{'osname'} eq 'MSWin32') { $MCSTAS::sys_dir = "c:\\mcstas\\lib"; } else { $MCSTAS::sys_dir = "/usr/local/lib/mcstas"; } } $MCSTAS::perl_dir = "$MCSTAS::sys_dir/tools/perl"; } use lib $MCSTAS::perl_dir; require "mcstas_config.perl"; use FileHandle; use File::Basename; require "mcrunlib.pl"; my $is_single_file= 0; # true when doc requested for a single component my $is_user_lib = 0; # true when doc requested for a directory my $lib_dir = $MCSTAS::sys_dir; my $out_file = "index.html"; # default name for output of catalog my $use_local = 0; # true when also looking into current path my $single_comp_name = 0; # component single name my $browser = $MCSTAS::mcstas_config{'BROWSER'}; my $is_forced = 0; # true when force re-writting of existing HTML sub show_header { # output in text mode my ($d) = @_; my ($i); print "######## $d->{'type'}: $d->{'name'} #####################\n"; if ($d->{'type'} eq "Instrument") { print "[Site]: $d->{'site'}\n"; } print "[Author]: $d->{'identification'}{'author'}\n"; print "[Origin]: $d->{'identification'}{'origin'}\n"; print "[Date]: $d->{'identification'}{'date'}\n"; print "[Version]:$d->{'identification'}{'version'}\n"; for $i (@{$d->{'identification'}{'history'}}) { print "[Modified by]: $i\n"; } print "\n"; print $d->{'identification'}{'short'}; print "######## Input parameters: ##############################\n"; for $i (@{$d->{'inputpar'}}) { if(defined($d->{'parhelp'}{$i}{'default'})) { print "<$i=$d->{'parhelp'}{$i}{'default'}>: "; } else { print "<$i>: "; } if($d->{'parhelp'}{$i}) { print "[$d->{'parhelp'}{$i}{'unit'}] " if $d->{'parhelp'}{$i}{'unit'}; print "$d->{'parhelp'}{$i}{'text'}" if $d->{'parhelp'}{$i}{'text'}; # text finishes by \n print("\n"); } else { print("\n"); } } if (@{$d->{'outputpar'}}) { print "\n######## Output parameters: #############################\n"; for $i (@{$d->{'outputpar'}}) { print "<$i>: "; if($d->{'parhelp'}{$i}) { print "[$d->{'parhelp'}{$i}{'unit'}] " if $d->{'parhelp'}{$i}{'unit'}; print "$d->{'parhelp'}{$i}{'text'}" if $d->{'parhelp'}{$i}{'text'}; # text finishes by \n print("\n"); } else { print("\n"); } } } if($d->{'description'}) { print "\n######## Description: ###################################\n"; print $d->{'description'}; } print "\n#########################################################\n"; } # # Output the start of the main component index HTML table # parameters: ($filehandle, $toolbar); sub html_main_start { my ($f, $toolbar) = @_; print $f < McStas : Components/Instruments Library $toolbar

Components and Instruments from the Library for McStas

Names in Boldface denote components that are properly documented with comments in the source code.

END } # # Output the HTML table row describing component with information in # $d to file handle $f. # parameters: ($data, $filehandle, $basename) sub html_table_entry { my ($d, $f, $bn, $vn) = @_; print $f "\n"; print $f " "; print $f "" if %{$d->{'parhelp'}}; if ($d->{'type'} eq "Instrument") { print $f "$d->{'site'} $d->{'name'} ($d->{'path'})"; } else { print $f "$d->{'name'}"; } print $f "" if %{$d->{'parhelp'}}; print $f "\n"; print $f "$d->{'identification'}{'origin'}\n"; print $f "$d->{'identification'}{'author'}\n"; print $f ""; print $f "{'ext'}\">$d->{'ext'}"; print $f "\n"; print $f "$d->{'identification'}{'short'}\n"; print $f "\n\n"; } # # Output the end of the main component index HTML table # parameters: ($filehandle, $toolbar); sub html_main_end { my ($f, $toolbar) = @_; my $date = gmtime; print $f <This Component list was updated on $date.
[ McStas at ILL | McStas at Risø ]


Generated by McDoc, Maintained by Emmanuel Farhi <farhi\@ill.fr> and Peter Willendrup <peter.willendrup\@risoe.dk>. Contact us for any comments.
END } # # Output the HTML table for either input or output parameters. # sub gen_param_table { my ($f, $ps, $qs) = @_; my $i; # Avoid outputting empty table. unless(@$ps) { print $f "None.\n"; return; } print $f "\n"; print $f "\n"; for $i (@$ps) { my $default = $qs->{$i}{'default'}; print $f "\n"; if($qs->{$i}{'unit'} && $qs->{$i}{'text'}) { print $f " \n"; print $f " \n"; } else { print $f " \n"; } print $f "\n"; } print $f "
Name Unit Description Default
"; print $f "" unless defined($default); print $f "$i"; print $f "" unless defined($default); print $f "$qs->{$i}{'unit'}$qs->{$i}{'text'} ", defined($default) ? $default : " ", "
\n\n"; } # # Generate description web page from component with information in $d. # parameters: ($data, $basename, $name); sub gen_html_description { my ($d, $bn, $n) = @_; my $f = new FileHandle; my $toolbar = <<'TB_END';

[ Identification | Description | Input parameters | Output parameters | Links ]

TB_END my $is_opened = 0; my $valid_name= ""; $n=~ s|.comp\Z||; # remove trailing extension $n=~ s|.cmp\Z||; # remove trailing extension $n=~ s|.com\Z||; # remove trailing extension $n=~ s|.instr\Z||; # remove trailing extension $valid_name = $bn; if (open($f, ">$bn.html")) { # use component location $is_opened = 1; } if (((not $is_opened) && $is_forced) || (not -f "$valid_name.html")) { if (open($f, ">$n.html")) { # create locally $is_opened = 1; $valid_name = $n; } } if ($is_single_file) { $out_file = "$valid_name.html"; } if ($is_opened) { print $f "\n"; print $f "\n"; if ($d->{'type'} eq "Instrument") { print $f "McStas: $d->{'name'} $d->{'type'} at $d->{'site'}\n"; } else { print $f "McStas: $d->{'name'} $d->{'type'}\n"; } print $f "\n"; print $f "\n\n"; print $f "\n\n$toolbar\n"; print $f "

The $d->{'name'} $d->{'type'}

\n\n"; print $f "$d->{'identification'}{'short'}\n\n"; print $f "

Identification

\n"; print $f "\n
    \n"; if ($d->{'type'} eq "Instrument") { print $f "
  • Site: $d->{'site'}\n"; } print $f "
  • Author:$d->{'identification'}{'author'}\n"; print $f "
  • Origin:$d->{'identification'}{'origin'}\n"; print $f "
  • Date:$d->{'identification'}{'date'}\n"; print $f "
  • Version:$d->{'identification'}{'version'}\n"; if(@{$d->{'identification'}{'history'}}) { my $entry; print $f "
  • Modification history:
      \n"; for $entry (@{$d->{'identification'}{'history'}}) { print $f "
    • $entry\n"; } print $f "
    \n"; } print $f "
\n"; if($d->{'description'}) { print $f "

Description

\n"; print $f "\n
\n$d->{'description'}
\n"; if ($bn =~ m/obsolete/i || $n =~ m/obsolete/i) { print $f "WARNING: This is an obsolete $d->{'type'}."; print $f "Please avoid usage whenever possible.\n"; } if ($bn =~ m/contrib/i || $n =~ m/contrib/i) { print $f "WARNING: This is a contributed $d->{'type'}.\n"; } } print $f "\n

Input parameters

\n"; if(@{$d->{'inputpar'}}) { print $f "Parameters in boldface are required;\n"; print $f "the others are optional.\n"; } gen_param_table($f, $d->{'inputpar'}, $d->{'parhelp'}); if (@{$d->{'outputpar'}}) { print $f "\n

Output parameters

\n"; gen_param_table($f, $d->{'outputpar'}, $d->{'parhelp'}); } print $f "\n

Links

\n\n
    \n"; print $f "
  • {'path'}\">Source code "; print $f "for $d->{'name'}.$d->{'ext'}.\n"; # Additional links from component comment header go here. my $link; for $link (@{$d->{'links'}}) { print $f "
  • $link"; } print $f "
\n"; print $f "
\n$toolbar\n
\n"; print $f "Generated automatically by McDoc, Peter Willendrup\n"; print $f "<"; print $f "peter.willendrup\@risoe.dk> /\n"; my $date = gmtime; print $f "$date"; print $f "
\n"; print $f "\n"; close $f; } else { if (not -f "$valid_name.html") { print "mcdoc: Cannot open $valid_name.html. Use -f option to force.\n"; } } return $valid_name; } # # Add component with info in $d to web page handle $f, and generate # stand-alone documentation page. $bn is the base name (file name # without trailing .comp). # parameters: ($data, $filehandle, $basename, $name); sub add_comp_html { my ($d, $f, $bn, $n) = @_; my $vn; $vn = gen_html_description($d, $bn, $n); if ($f) { html_table_entry($d, $f, $bn, $vn); } } # # Add a whole section of components, given the section directory name. # parameters: ($lib_dir, $section, $section_header, $filehandle); sub add_comp_section_html { my ($lib, $sec, $header, $filehandle) = @_; my $sec_orig = $sec; if ($sec =~ "local") { $sec = getcwd(); $single_comp_name = basename($single_comp_name); $is_forced=1; } # local components $sec = "$lib/$sec" unless -d $sec; if(opendir(DIR, $sec)) { my @comps = readdir(DIR); closedir DIR; if ($is_forced) { # test if the given comp/instr name is an actual file name if (-f "$single_comp_name") { push @comps, $single_comp_name; } } return unless @comps; if ($filehandle) { print $filehandle < $header END } # end if filehandle my ($comp, $name); my $single_comp_name_base; # extract the requested comp/instr name to look for, removing possible path $single_comp_name_base= basename($single_comp_name); for $name (sort(@comps)) { my $comp = "$sec/$name"; my $does_match = 0; my $name_base; my $basename; next if (-d "$name"); # skip directories # extract the scanned comp/instr name from lib, removing possible path $name_base = basename($name); # with extension if ($single_comp_name_base =~ /^(.*)\.(com|comp|cmp|instr)$/) { # requested doc name includes extension: search exact match if($name_base =~ $single_comp_name_base) { $does_match = 2; } } elsif ($name_base =~ $single_comp_name_base) { # requested doc name does not contain an extension: search all matches $does_match = 1; } # skip non comp/instr if ($comp !~ /^(.*)\.(com|comp|cmp|instr)$/) { if ($comp !~ /^(.*)\.(htm|html)$/ && $does_match) { print STDOUT "mcdoc: $comp (not a component/instrument)\n"; } next } else { $basename = $1; } # without extension if (($is_single_file && $does_match) || (not $is_single_file)) { $data = component_information($comp); if (not defined($data)) { print STDERR "mcdoc: Failed to get information for component/instrument '$comp'"; } else { print STDOUT "mcdoc: $comp\n"; if ($is_single_file) { $data->{'path'} = $comp; } else { $data->{'path'} = $name; } if ($is_single_file && $browser =~ "text") { show_header($data); # display single comp as text if ($sec =~ m/obsolete/i) { print "WARNING: This is an obsolete $data->{'type'}. \n"; print " Please avoid usage whenever possible.\n"; } if ($sec =~ m/contrib/i) { print "WARNING: This is a contributed $data->{'type'}. \n"; } } else { add_comp_html($data, $filehandle, $basename, $name); } } } last if $does_match == 2; } # end for if ($filehandle) { print $filehandle < END } # end if filehandle } #end if open DIR } # Start of main =============================== my $index = 0; my $file; my $show_website = 0; my $show_manual = 0; my $show_compman = 0; my $show_tutorial = 0; for($i = 0; $i < @ARGV; $i++) { $_ = $ARGV[$i]; # Options specific to mcdoc. if(/^--show$/i || /^-s$/i || /^--html$/i) { $browser = $MCSTAS::mcstas_config{'BROWSER'}; } elsif(/^--text$/i || /^-t$/i) { $browser = "text"; } elsif(/^--web$/i || /^-w$/i) { $show_website = 1; } elsif(/^--manual$/i || /^-m$/i) { $show_manual = 1; } elsif(/^--comp$/i || /^-c$/i) { $show_compman = 1; } elsif(/^--tutorial$/i) { $show_tutorial = 1; } elsif(/^--local$/i) { $use_local = 1; } elsif(/^--force$/i || /^-f$/i) { $is_forced = 1; } elsif(/^--help$/i || /^-h$/i || /^-v$/i) { print "Usage: mcdoc [options] \n"; print "Generate/show component/instrument documentation using $browser\n"; print " -f --force Force re-writting of existing HTML doc locally\n"; print " -h --help Show this help\n"; print " -l --tools Display the McStas tools list\n"; print " -m --manual Open the McStas User manual\n"; print " -c --comp Open the McStas Component manual\n"; print " -t --text For single component, display as text\n"; print " -w --web Open the McStas web page http://www.mcstas.org/\n"; print " --tutorial Open the McStas tutorial from the local McStas library\n"; print "SEE ALSO: mcstas, mcdoc, mcplot, mcrun, mcgui, mcresplot, mcstas2vitess\n"; print "DOC: Please visit http://www.mcstas.org/\n"; exit; } elsif(/^--tools$/i || /^-l$/) { print "McStas Tools\n"; print " mcstas Main instrument compiler\n"; print " mcrun Instrument maker and execution utility\n"; print " mcgui Graphical User Interface instrument builder\n"; print " mcdoc Component library documentation generator/viewer\n"; print " mcplot Simulation result viewer\n"; print " mcdisplay Instrument geometry viewer\n"; print " mcresplot Instrument resolution function viewer\n"; print " mcstas2vitess McStas to Vitess component translation utility\n"; print " mcconvert Matlab <-> Scilab script conversion tool\n"; print "When used with the -h flag, all tools display a specific help.\n"; print "SEE ALSO: mcstas, mcdoc, mcplot, mcrun, mcgui, mcresplot, mcstas2vitess\n"; print "DOC: Please visit http://www.mcstas.org/\n"; exit; } else { $file = $ARGV[$i]; $index++; } } # end for if ($show_website) { # open the index.html my $cmd = "$MCSTAS::mcstas_config{'BROWSER'} http://www.mcstas.org/ "; print "mcdoc: Starting $cmd\n"; system("$cmd\n"); die "mcdoc: web site done.\n"; } if ($show_manual) { # open the manual using embedded acroread plugin $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $MCSTAS::sys_dir/doc/mcstas-manual.pdf"; print "mcdoc: Starting $cmd\n"; system("$cmd\n"); die "mcdoc: User manual done.\n"; } if ($show_compman) { # open the component manual $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $MCSTAS::sys_dir/doc/mcstas-components.pdf"; print "mcdoc: Starting $cmd\n"; system("$cmd\n"); die "mcdoc: Component manual done.\n"; } if ($show_tutorial) { # open the index.html $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $MCSTAS::sys_dir/doc/tutorial/html/tutorial.html"; print "mcdoc: Starting $cmd\n"; system("$cmd\n"); die "mcdoc: Tutorial done.\n"; } # if 'file' is given if ($index > 0) { if (-d $file) { $lib_dir = $file; } # get doc of the given dir else { $is_single_file=1; $single_comp_name = $file; } # search locally and in lib $use_local=1; # will also search locally } my $filehandle = 0; my @sections; my %section_headers; if (not $is_single_file) { # Open the local documentation file $filehandle = new FileHandle; my $no_lib_write = 0; if (not open($filehandle, ">$lib_dir/$out_file")) { $no_lib_write = 1; } if ($no_lib_write) { my $no_local_write = 0; if (not open($filehandle, ">$out_file")) { $no_local_write = 1; } if ($no_local_write) { $filehandle = 0; # will not write the catalog print STDERR "mcdoc: Could not open $out_file for writing.\n"; } } else { $out_file = "$lib_dir/$out_file"; } if (not $filehandle) { if (-f "$lib_dir/$out_file") { $out_file = "$lib_dir/$out_file"; } elsif (not -f $out_file) { print STDERR "mcdoc: Could not find the $out_file library catalog.\n"; } } } if ($use_local) { # define local and lib sections @sections = ("sources", "optics", "samples", "monitors", "misc", "contrib", "obsolete","examples","local","data","share","doc"); %section_headers = ("sources" => 'Sources', "optics" => 'Optics', "samples" => 'Samples', "monitors" => 'Detectors and monitors', "contrib" => 'Contributed components', "misc" => 'Misc', "obsolete" => 'Obsolete (avoid usage whenever possible)', "examples" => 'Instrument Examples', "local" => 'Local components', "data" => 'Data files', "share" => 'Shared libraries', "doc" => 'Documentation'); } else { # define lib sections @sections = ("sources", "optics", "samples", "monitors", "misc", "contrib","examples"); %section_headers = ("sources" => 'Sources', "optics" => 'Optics', "samples" => 'Samples', "monitors" => 'Detectors and monitors', "contrib" => 'Contributed components', "misc" => 'Misc', "obsolete" => 'Obsolete (avoid usage whenever possible)', "examples" => 'Instrument Examples',); } my @tblist = map "$_", @sections; my $toolbar = "

\n [ " . join("\n | ", @tblist) . " ]\n

\n"; $toolbar .= "

\n [ User Manual | Component Manual | McStas tutorial | Data files ]\n

\n"; if ($filehandle) { html_main_start($filehandle, $toolbar); } # open each section, look for comps, add entry in index.html, # and generate comp doc my $sec; my $is_forced_orig = $is_forced; for $sec (@sections) { add_comp_section_html($lib_dir, $sec, $section_headers{$sec}, $filehandle); $is_forced = $is_forced_orig; # may have been changed globally (sec == local) } if ($filehandle) { html_main_end($filehandle, $toolbar); close($filehandle); } if (-f $out_file) { if ($browser ne "text") { # open the index.html my $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $out_file"; print "mcdoc: Starting $cmd\n"; system("$cmd\n"); } }
Name Origin Author(s) Source code Description