| 1 | #! /usr/bin/perl -w |
|---|
| 2 | |
|---|
| 3 | # Determine the path to the McStas system directory. This must be done |
|---|
| 4 | # in the BEGIN block so that it can be used in a "use lib" statement |
|---|
| 5 | # afterwards. |
|---|
| 6 | |
|---|
| 7 | use Config; |
|---|
| 8 | use Cwd; |
|---|
| 9 | BEGIN { |
|---|
| 10 | # default configuration (for all high level perl scripts) |
|---|
| 11 | if($ENV{"MCSTAS"}) { |
|---|
| 12 | $MCSTAS::sys_dir = $ENV{"MCSTAS"}; |
|---|
| 13 | } else { |
|---|
| 14 | if ($Config{'osname'} eq 'MSWin32') { |
|---|
| 15 | $MCSTAS::sys_dir = "c:\\mcstas\\lib"; |
|---|
| 16 | } else { |
|---|
| 17 | $MCSTAS::sys_dir = "/usr/local/lib/mcstas"; |
|---|
| 18 | } |
|---|
| 19 | } |
|---|
| 20 | $MCSTAS::perl_dir = "$MCSTAS::sys_dir/tools/perl"; |
|---|
| 21 | } |
|---|
| 22 | |
|---|
| 23 | use lib $MCSTAS::perl_dir; |
|---|
| 24 | require "mcstas_config.perl"; |
|---|
| 25 | |
|---|
| 26 | # Overload with user's personal config |
|---|
| 27 | if ($ENV{"HOME"} && -e $ENV{"HOME"}."/.mcstas/mcstas_config.perl") { |
|---|
| 28 | require $ENV{"HOME"}."/.mcstas/mcstas_config.perl"; |
|---|
| 29 | } |
|---|
| 30 | |
|---|
| 31 | use FileHandle; |
|---|
| 32 | use File::Basename; |
|---|
| 33 | require "mcrunlib.pl"; |
|---|
| 34 | |
|---|
| 35 | my $is_single_file= 0; # true when doc requested for a single component |
|---|
| 36 | my $is_user_lib = 0; # true when doc requested for a directory |
|---|
| 37 | my $lib_dir = $MCSTAS::sys_dir; |
|---|
| 38 | my $out_file = "index.html"; # default name for output of catalog |
|---|
| 39 | my $use_local = 0; # true when also looking into current path |
|---|
| 40 | my $single_comp_name = 0; # component single name |
|---|
| 41 | my $browser = $MCSTAS::mcstas_config{'BROWSER'}; |
|---|
| 42 | my $is_forced = 0; # true when force re-writting of existing HTML |
|---|
| 43 | my @valid_names; # Full list of possible comp matches |
|---|
| 44 | my $HTTP_SYSDIR = "file://".$MCSTAS::sys_dir; # Many browsers need a file:// to properly access local files |
|---|
| 45 | $HTTP_SYSDIR =~ s!\\!/!g; |
|---|
| 46 | |
|---|
| 47 | sub show_header { # output in text mode |
|---|
| 48 | my ($d) = @_; |
|---|
| 49 | my ($i); |
|---|
| 50 | print "######## $d->{'type'}: $d->{'name'} #####################\n"; |
|---|
| 51 | if ($d->{'type'} eq "Instrument") { |
|---|
| 52 | print "[Site]: $d->{'site'}\n"; |
|---|
| 53 | } |
|---|
| 54 | print "[Author]: $d->{'identification'}{'author'}\n"; |
|---|
| 55 | print "[Origin]: $d->{'identification'}{'origin'}\n"; |
|---|
| 56 | print "[Date]: $d->{'identification'}{'date'}\n"; |
|---|
| 57 | print "[Version]:$d->{'identification'}{'version'}\n"; |
|---|
| 58 | for $i (@{$d->{'identification'}{'history'}}) { |
|---|
| 59 | print "[Modified by]: $i\n"; |
|---|
| 60 | } |
|---|
| 61 | print "\n"; |
|---|
| 62 | print $d->{'identification'}{'short'}; |
|---|
| 63 | print "######## Input parameters: ##############################\n"; |
|---|
| 64 | for $i (@{$d->{'inputpar'}}) { |
|---|
| 65 | if(defined($d->{'parhelp'}{$i}{'default'})) { |
|---|
| 66 | print "<$i=$d->{'parhelp'}{$i}{'default'}>: "; |
|---|
| 67 | } else { |
|---|
| 68 | print "<$i>: "; |
|---|
| 69 | } |
|---|
| 70 | if($d->{'parhelp'}{$i}) { |
|---|
| 71 | print "[$d->{'parhelp'}{$i}{'unit'}] " |
|---|
| 72 | if $d->{'parhelp'}{$i}{'unit'}; |
|---|
| 73 | print "$d->{'parhelp'}{$i}{'text'}" |
|---|
| 74 | if $d->{'parhelp'}{$i}{'text'}; # text finishes by \n |
|---|
| 75 | print("\n"); |
|---|
| 76 | } else { |
|---|
| 77 | print("<Undocumented>\n"); |
|---|
| 78 | } |
|---|
| 79 | } |
|---|
| 80 | if (@{$d->{'outputpar'}}) { |
|---|
| 81 | print "\n######## Output parameters: #############################\n"; |
|---|
| 82 | for $i (@{$d->{'outputpar'}}) { |
|---|
| 83 | print "<$i>: "; |
|---|
| 84 | if($d->{'parhelp'}{$i}) { |
|---|
| 85 | print "[$d->{'parhelp'}{$i}{'unit'}] " |
|---|
| 86 | if $d->{'parhelp'}{$i}{'unit'}; |
|---|
| 87 | print "$d->{'parhelp'}{$i}{'text'}" |
|---|
| 88 | if $d->{'parhelp'}{$i}{'text'}; # text finishes by \n |
|---|
| 89 | print("\n"); |
|---|
| 90 | } else { |
|---|
| 91 | print("<Undocumented>\n"); |
|---|
| 92 | } |
|---|
| 93 | } |
|---|
| 94 | } |
|---|
| 95 | if($d->{'description'}) { |
|---|
| 96 | print "\n######## Description: ###################################\n"; |
|---|
| 97 | print $d->{'description'}; |
|---|
| 98 | } |
|---|
| 99 | print "\n#########################################################\n"; |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | # |
|---|
| 103 | # Output the start of the main component index HTML table |
|---|
| 104 | # parameters: ($filehandle, $toolbar); |
|---|
| 105 | sub html_main_start { |
|---|
| 106 | my ($f, $toolbar) = @_; |
|---|
| 107 | print $f <<END; |
|---|
| 108 | <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"> |
|---|
| 109 | <HTML> |
|---|
| 110 | <HEAD> |
|---|
| 111 | <META NAME="GENERATOR" CONTENT="McDoc"> |
|---|
| 112 | <TITLE>McStas : Components/Instruments Library </TITLE> |
|---|
| 113 | </HEAD> |
|---|
| 114 | <BODY> |
|---|
| 115 | |
|---|
| 116 | $toolbar |
|---|
| 117 | <CENTER><H1>Components and Instruments from the Library for <i>McStas</i></H1></CENTER> |
|---|
| 118 | |
|---|
| 119 | <P> Names in <B>Boldface</B> denote components that are properly |
|---|
| 120 | documented with comments in the source code.</P> |
|---|
| 121 | END |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | # |
|---|
| 125 | # Output the HTML table row describing component with information in |
|---|
| 126 | # $d to file handle $f. |
|---|
| 127 | # parameters: ($data, $filehandle, $basename) |
|---|
| 128 | sub html_table_entry { |
|---|
| 129 | my ($d, $f, $bn, $vn) = @_; |
|---|
| 130 | print $f "<TR>\n"; |
|---|
| 131 | print $f "<TD> "; |
|---|
| 132 | print $f "<B>" if %{$d->{'parhelp'}}; |
|---|
| 133 | my $link = "file://".$vn; |
|---|
| 134 | $link =~ s!\\!/!g; |
|---|
| 135 | |
|---|
| 136 | if ($d->{'type'} eq "Instrument") { |
|---|
| 137 | print $f "$d->{'site'} <A HREF=\"$link.html\">$d->{'name'}</A> ($d->{'path'})"; |
|---|
| 138 | } else { |
|---|
| 139 | print $f "<A HREF=\"$link.html\">$d->{'name'}</A>"; |
|---|
| 140 | } |
|---|
| 141 | print $f "</B>" if %{$d->{'parhelp'}}; |
|---|
| 142 | print $f "</TD>\n"; |
|---|
| 143 | |
|---|
| 144 | print $f "<TD>$d->{'identification'}{'origin'}</TD>\n"; |
|---|
| 145 | |
|---|
| 146 | print $f "<TD>$d->{'identification'}{'author'}</TD>\n"; |
|---|
| 147 | |
|---|
| 148 | $link = "file://".$bn; |
|---|
| 149 | $link =~ s!\\!/!g; |
|---|
| 150 | |
|---|
| 151 | print $f "<TD>"; |
|---|
| 152 | print $f "<A HREF=\"$link.$d->{'ext'}\">$d->{'ext'}</A>"; |
|---|
| 153 | print $f "</TD>\n"; |
|---|
| 154 | |
|---|
| 155 | print $f "<TD>$d->{'identification'}{'short'}</TD>\n"; |
|---|
| 156 | print $f "</TR>\n\n"; |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | # |
|---|
| 160 | # Output the end of the main component index HTML table |
|---|
| 161 | # parameters: ($filehandle, $toolbar); |
|---|
| 162 | sub html_main_end { |
|---|
| 163 | my ($f, $toolbar) = @_; |
|---|
| 164 | my $date = gmtime; |
|---|
| 165 | |
|---|
| 166 | print $f <<END; |
|---|
| 167 | <P>This Component list was updated on $date. |
|---|
| 168 | <HR WIDTH="100%"> |
|---|
| 169 | <CENTER> |
|---|
| 170 | [ <A HREF="http://www.ill.fr/tas/mcstas/"><I>McStas</I> at ILL</A> |
|---|
| 171 | | <A href="http://www.mcstas.org/"><I>McStas</I> at Risø</A> ] |
|---|
| 172 | </CENTER> |
|---|
| 173 | |
|---|
| 174 | <P><BR> |
|---|
| 175 | <ADDRESS> |
|---|
| 176 | Generated by McDoc, |
|---|
| 177 | Maintained by Emmanuel Farhi <<a href="mailto:farhi\@ill.fr">farhi\@ill.fr</a>> |
|---|
| 178 | and Peter Willendrup <<a href="mailto:peter.willendrup\@risoe.dk">peter.willendrup\@risoe.dk</a>>. |
|---|
| 179 | Contact us for any comments. |
|---|
| 180 | </ADDRESS> |
|---|
| 181 | </BODY></HTML> |
|---|
| 182 | END |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | # |
|---|
| 186 | # Output the HTML table for either input or output parameters. |
|---|
| 187 | # |
|---|
| 188 | sub gen_param_table { |
|---|
| 189 | my ($f, $ps, $qs) = @_; |
|---|
| 190 | my $i; |
|---|
| 191 | # Avoid outputting empty table. |
|---|
| 192 | unless(@$ps) { |
|---|
| 193 | print $f "None.\n"; |
|---|
| 194 | return; |
|---|
| 195 | } |
|---|
| 196 | print $f "<TABLE BORDER=1>\n"; |
|---|
| 197 | print $f "<TR><TH>Name</TH> <TH>Unit</TH> <TH>Description</TH> <TH>Default</TH></TR>\n"; |
|---|
| 198 | for $i (@$ps) { |
|---|
| 199 | my $default = $qs->{$i}{'default'}; |
|---|
| 200 | print $f "<TR> <TD>"; |
|---|
| 201 | print $f "<B>" unless defined($default); |
|---|
| 202 | print $f "$i"; |
|---|
| 203 | print $f "</B>" unless defined($default); |
|---|
| 204 | print $f "</TD>\n"; |
|---|
| 205 | if($qs->{$i}{'unit'} && $qs->{$i}{'text'}) { |
|---|
| 206 | print $f " <TD>$qs->{$i}{'unit'}</TD>\n"; |
|---|
| 207 | print $f " <TD>$qs->{$i}{'text'}</TD>\n"; |
|---|
| 208 | } else { |
|---|
| 209 | print $f " <TD></TD> <TD></TD>\n"; |
|---|
| 210 | } |
|---|
| 211 | print $f "<TD ALIGN=RIGHT>", defined($default) ? |
|---|
| 212 | $default : " ", "</TD> </TR>\n"; |
|---|
| 213 | } |
|---|
| 214 | print $f "</TABLE>\n\n"; |
|---|
| 215 | } |
|---|
| 216 | |
|---|
| 217 | # |
|---|
| 218 | # Generate description web page from component with information in $d. |
|---|
| 219 | # parameters: ($data, $basename, $name); |
|---|
| 220 | sub gen_html_description { |
|---|
| 221 | my ($d, $bn, $n) = @_; |
|---|
| 222 | my $f = new FileHandle; |
|---|
| 223 | my $toolbar = <<'TB_END'; |
|---|
| 224 | <P ALIGN=CENTER> |
|---|
| 225 | [ <A href="#id">Identification</A> |
|---|
| 226 | | <A href="#desc">Description</A> |
|---|
| 227 | | <A href="#ipar">Input parameters</A> |
|---|
| 228 | | <A href="#opar">Output parameters</A> |
|---|
| 229 | | <A href="#links">Links</A> ] |
|---|
| 230 | </P> |
|---|
| 231 | TB_END |
|---|
| 232 | my $is_opened = 0; |
|---|
| 233 | my $valid_name= ""; |
|---|
| 234 | $n=~ s|.comp\Z||; # remove trailing extension |
|---|
| 235 | $n=~ s|.cmp\Z||; # remove trailing extension |
|---|
| 236 | $n=~ s|.com\Z||; # remove trailing extension |
|---|
| 237 | $n=~ s|.instr\Z||; # remove trailing extension |
|---|
| 238 | $valid_name = $bn; |
|---|
| 239 | if (open($f, ">$bn.html")) { # use component location |
|---|
| 240 | $is_opened = 1; |
|---|
| 241 | } |
|---|
| 242 | if (((not $is_opened) && $is_forced) || (not -f "$valid_name.html")) { |
|---|
| 243 | if (open($f, ">$n.html")) { # create locally |
|---|
| 244 | $is_opened = 1; |
|---|
| 245 | $valid_name = $n; |
|---|
| 246 | } |
|---|
| 247 | } |
|---|
| 248 | |
|---|
| 249 | if ($is_single_file) { |
|---|
| 250 | $out_file = "$valid_name.html"; |
|---|
| 251 | push @valid_names, $out_file; |
|---|
| 252 | } |
|---|
| 253 | |
|---|
| 254 | if ($is_opened) { |
|---|
| 255 | |
|---|
| 256 | print $f "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"; |
|---|
| 257 | print $f "<HTML><HEAD>\n"; |
|---|
| 258 | if ($d->{'type'} eq "Instrument") { |
|---|
| 259 | print $f "<TITLE>McStas: $d->{'name'} $d->{'type'} at $d->{'site'}</TITLE>\n"; |
|---|
| 260 | } else { |
|---|
| 261 | print $f "<TITLE>McStas: $d->{'name'} $d->{'type'}</TITLE>\n"; |
|---|
| 262 | } |
|---|
| 263 | print $f "<LINK REV=\"made\" HREF=\"mailto:peter.willendrup\@risoe.dk\">\n"; |
|---|
| 264 | print $f "</HEAD>\n\n"; |
|---|
| 265 | print $f "<BODY>\n\n$toolbar\n"; |
|---|
| 266 | print $f "<H1>The <CODE>$d->{'name'}</CODE> $d->{'type'}</H1>\n\n"; |
|---|
| 267 | print $f "$d->{'identification'}{'short'}\n\n"; |
|---|
| 268 | print $f "<H2><A NAME=id></A>Identification</H2>\n"; |
|---|
| 269 | print $f "\n<UL>\n"; |
|---|
| 270 | if ($d->{'type'} eq "Instrument") { |
|---|
| 271 | print $f " <LI> <B>Site: $d->{'site'}</B>\n"; |
|---|
| 272 | } |
|---|
| 273 | print $f " <LI> <B>Author:</B>$d->{'identification'}{'author'}</B>\n"; |
|---|
| 274 | print $f " <LI> <B>Origin:</B>$d->{'identification'}{'origin'}</B>\n"; |
|---|
| 275 | print $f " <LI> <B>Date:</B>$d->{'identification'}{'date'}</B>\n"; |
|---|
| 276 | print $f " <LI> <B>Version:</B>$d->{'identification'}{'version'}</B>\n"; |
|---|
| 277 | if(@{$d->{'identification'}{'history'}}) { |
|---|
| 278 | my $entry; |
|---|
| 279 | print $f " <LI> <B>Modification history:</B> <UL>\n"; |
|---|
| 280 | for $entry (@{$d->{'identification'}{'history'}}) { |
|---|
| 281 | print $f " <LI> $entry\n"; |
|---|
| 282 | } |
|---|
| 283 | print $f " </UL>\n"; |
|---|
| 284 | } |
|---|
| 285 | print $f "</UL>\n"; |
|---|
| 286 | if($d->{'description'}) { |
|---|
| 287 | print $f "<H2><A NAME=desc></A>Description</H2>\n"; |
|---|
| 288 | print $f "\n<PRE>\n$d->{'description'}</PRE>\n"; |
|---|
| 289 | if ($bn =~ m/obsolete/i || $n =~ m/obsolete/i) { |
|---|
| 290 | print $f "WARNING: <B>This is an obsolete $d->{'type'}."; |
|---|
| 291 | print $f "Please avoid usage whenever possible.</B>\n"; |
|---|
| 292 | } |
|---|
| 293 | if ($bn =~ m/contrib/i || $n =~ m/contrib/i) { |
|---|
| 294 | print $f "WARNING: <B>This is a contributed $d->{'type'}.</B>\n"; |
|---|
| 295 | } |
|---|
| 296 | } |
|---|
| 297 | print $f "\n<H2><A NAME=ipar></A>Input parameters</H2>\n"; |
|---|
| 298 | if(@{$d->{'inputpar'}}) { |
|---|
| 299 | print $f "Parameters in <B>boldface</B> are required;\n"; |
|---|
| 300 | print $f "the others are optional.\n"; |
|---|
| 301 | } |
|---|
| 302 | gen_param_table($f, $d->{'inputpar'}, $d->{'parhelp'}); |
|---|
| 303 | if (@{$d->{'outputpar'}}) { |
|---|
| 304 | print $f "\n<H2><A NAME=opar></A>Output parameters</H2>\n"; |
|---|
| 305 | gen_param_table($f, $d->{'outputpar'}, $d->{'parhelp'}); |
|---|
| 306 | } |
|---|
| 307 | print $f "\n<H2><A NAME=links></A>Links</H2>\n\n<UL>\n"; |
|---|
| 308 | |
|---|
| 309 | print $f " <LI> <A HREF=\"$d->{'path'}\">Source code</A> "; |
|---|
| 310 | print $f "for <CODE>$d->{'name'}.$d->{'ext'}</CODE>.\n"; |
|---|
| 311 | # Additional links from component comment header go here. |
|---|
| 312 | my $link; |
|---|
| 313 | for $link (@{$d->{'links'}}) { |
|---|
| 314 | print $f " <LI> $link"; |
|---|
| 315 | } |
|---|
| 316 | print $f "</UL>\n"; |
|---|
| 317 | print $f "<HR>\n$toolbar\n<ADDRESS>\n"; |
|---|
| 318 | print $f "Generated automatically by McDoc, Peter Willendrup\n"; |
|---|
| 319 | print $f "<<A HREF=\"mailto:peter.willendrup\@risoe.dk\">"; |
|---|
| 320 | print $f "peter.willendrup\@risoe.dk</A>> /\n"; |
|---|
| 321 | my $date = gmtime; |
|---|
| 322 | print $f "$date"; |
|---|
| 323 | print $f "</ADDRESS>\n"; |
|---|
| 324 | print $f "</BODY></HTML>\n"; |
|---|
| 325 | close $f; |
|---|
| 326 | } else { |
|---|
| 327 | if (not -f "$valid_name.html") { |
|---|
| 328 | print "mcdoc: Cannot open $valid_name.html. Use -f option to force.\n"; |
|---|
| 329 | } |
|---|
| 330 | } |
|---|
| 331 | return $valid_name; |
|---|
| 332 | } |
|---|
| 333 | |
|---|
| 334 | # |
|---|
| 335 | # Add component with info in $d to web page handle $f, and generate |
|---|
| 336 | # stand-alone documentation page. $bn is the base name (file name |
|---|
| 337 | # without trailing .comp). |
|---|
| 338 | # parameters: ($data, $filehandle, $basename, $name); |
|---|
| 339 | sub add_comp_html { |
|---|
| 340 | my ($d, $f, $bn, $n) = @_; |
|---|
| 341 | my $vn; |
|---|
| 342 | $vn = gen_html_description($d, $bn, $n); |
|---|
| 343 | if ($f) { html_table_entry($d, $f, $bn, $vn); } |
|---|
| 344 | } |
|---|
| 345 | |
|---|
| 346 | # |
|---|
| 347 | # Add a whole section of components, given the section directory name. |
|---|
| 348 | # parameters: ($lib_dir, $section, $section_header, $filehandle); |
|---|
| 349 | sub add_comp_section_html { |
|---|
| 350 | my ($lib, $sec, $header, $filehandle) = @_; |
|---|
| 351 | my $sec_orig = $sec; |
|---|
| 352 | if ($sec =~ "local") { $sec = getcwd(); $single_comp_name = basename($single_comp_name); $is_forced=1; } # local components |
|---|
| 353 | $sec = "$lib/$sec" unless -d $sec; |
|---|
| 354 | if(opendir(DIR, $sec)) { |
|---|
| 355 | my @comps = readdir(DIR); |
|---|
| 356 | closedir DIR; |
|---|
| 357 | if ($is_forced) { |
|---|
| 358 | # test if the given comp/instr name is an actual file name |
|---|
| 359 | if (-f "$single_comp_name") { |
|---|
| 360 | push @comps, $single_comp_name; |
|---|
| 361 | } |
|---|
| 362 | } |
|---|
| 363 | return unless @comps; |
|---|
| 364 | if ($filehandle) { |
|---|
| 365 | print $filehandle <<END; |
|---|
| 366 | |
|---|
| 367 | <P><A NAME="$sec_orig"></A> |
|---|
| 368 | $header |
|---|
| 369 | <TABLE BORDER COLS=5 WIDTH="100%" NOSAVE> |
|---|
| 370 | <TR> |
|---|
| 371 | <TD><B><I>Name</I></B></TD> |
|---|
| 372 | <TD WIDTH="10%"><B><I>Origin</I></B></TD> |
|---|
| 373 | <TD WIDTH="10%"><B><I>Author(s)</I></B></TD> |
|---|
| 374 | <TD><B><I>Source code</I></B></TD> |
|---|
| 375 | <TD><B><I>Description</I></B></TD> |
|---|
| 376 | </TR> |
|---|
| 377 | END |
|---|
| 378 | } # end if filehandle |
|---|
| 379 | my ($comp, $name); |
|---|
| 380 | my $single_comp_name_base; |
|---|
| 381 | # extract the requested comp/instr name to look for, removing possible path |
|---|
| 382 | $single_comp_name_base= basename($single_comp_name); |
|---|
| 383 | |
|---|
| 384 | for $name (sort(@comps)) { |
|---|
| 385 | my $comp = "$sec/$name"; |
|---|
| 386 | my $does_match = 0; |
|---|
| 387 | my $name_base; |
|---|
| 388 | my $basename; |
|---|
| 389 | next if (-d "$name"); # skip directories |
|---|
| 390 | # extract the scanned comp/instr name from lib, removing possible path |
|---|
| 391 | $name_base = basename($name); # with extension |
|---|
| 392 | if ($single_comp_name_base =~ /^(.*)\.(com|comp|cmp|instr)$/i) { |
|---|
| 393 | # requested doc name includes extension: search exact match |
|---|
| 394 | if((lc $name_base) =~ (lc $single_comp_name_base)) { |
|---|
| 395 | $does_match = 2; |
|---|
| 396 | } |
|---|
| 397 | } elsif ((lc $name_base) =~ (lc $single_comp_name_base)) { |
|---|
| 398 | # requested doc name does not contain an extension: search all matches |
|---|
| 399 | $does_match = 1; |
|---|
| 400 | } |
|---|
| 401 | # skip non comp/instr |
|---|
| 402 | if ($comp !~ /^(.*)\.(com|comp|cmp|instr)$/) |
|---|
| 403 | { |
|---|
| 404 | if ($comp !~ /^(.*)\.(htm|html)$/ && $does_match) { |
|---|
| 405 | print STDOUT "mcdoc: $comp (not a component/instrument)\n"; |
|---|
| 406 | } |
|---|
| 407 | next |
|---|
| 408 | } else { $basename = $1; } # without extension |
|---|
| 409 | if (($is_single_file && $does_match) |
|---|
| 410 | || (not $is_single_file)) { |
|---|
| 411 | $data = component_information($comp); |
|---|
| 412 | if (not defined($data)) { |
|---|
| 413 | print STDERR "mcdoc: Failed to get information for component/instrument '$comp'"; |
|---|
| 414 | } else { |
|---|
| 415 | print STDOUT "mcdoc: $comp\n"; |
|---|
| 416 | if ($is_single_file) { $data->{'path'} = $comp; } |
|---|
| 417 | else { $data->{'path'} = $name; } |
|---|
| 418 | if ($is_single_file && $browser =~ "text") { |
|---|
| 419 | show_header($data); # display single comp as text |
|---|
| 420 | if ($sec =~ m/obsolete/i) { |
|---|
| 421 | print "WARNING: This is an obsolete $data->{'type'}. \n"; |
|---|
| 422 | print " Please avoid usage whenever possible.\n"; |
|---|
| 423 | } |
|---|
| 424 | if ($sec =~ m/contrib/i) { |
|---|
| 425 | print "WARNING: This is a contributed $data->{'type'}. \n"; |
|---|
| 426 | } |
|---|
| 427 | } else { |
|---|
| 428 | add_comp_html($data, $filehandle, $basename, $name); |
|---|
| 429 | } |
|---|
| 430 | } |
|---|
| 431 | |
|---|
| 432 | } |
|---|
| 433 | last if $does_match == 2; |
|---|
| 434 | } # end for |
|---|
| 435 | if ($filehandle) { |
|---|
| 436 | print $filehandle <<END; |
|---|
| 437 | </TABLE> |
|---|
| 438 | |
|---|
| 439 | END |
|---|
| 440 | } # end if filehandle |
|---|
| 441 | } #end if open DIR |
|---|
| 442 | } |
|---|
| 443 | |
|---|
| 444 | # |
|---|
| 445 | # Add a search of components |
|---|
| 446 | sub add_comp_search_html { |
|---|
| 447 | my ($search, $filehandle, @Incomps) = @_; |
|---|
| 448 | my @comps; |
|---|
| 449 | my ($j, $sec, $comp, $inst, $suf); |
|---|
| 450 | for ($j=0; $j<@Incomps; $j++) { |
|---|
| 451 | ($comp,$sec,$suf) = fileparse($Incomps[$j],".html"); |
|---|
| 452 | print "Testing for $comp\n"; |
|---|
| 453 | $inst = "$sec$comp.instr"; |
|---|
| 454 | $comp = "$sec$comp.comp"; |
|---|
| 455 | if (-f "$comp") { |
|---|
| 456 | push @comps, $comp; |
|---|
| 457 | } elsif (-f "$inst") { |
|---|
| 458 | push @comps, $inst; |
|---|
| 459 | } |
|---|
| 460 | } |
|---|
| 461 | return unless @comps; |
|---|
| 462 | if ($filehandle) { |
|---|
| 463 | print $filehandle <<END; |
|---|
| 464 | <html> |
|---|
| 465 | <header><title>McDoc: Search result for "$search"</title></header> |
|---|
| 466 | <body> |
|---|
| 467 | <h1>Result of search for "$search" in your McStas library</h1> |
|---|
| 468 | <p>(Please note that only current dir and $lib_dir were searched, discarding 'obsolete' components) |
|---|
| 469 | <p><TABLE BORDER COLS=5 WIDTH="100%" NOSAVE> |
|---|
| 470 | <TR> |
|---|
| 471 | <TD><B><I>Name</I></B></TD> |
|---|
| 472 | <TD WIDTH="10%"><B><I>Origin</I></B></TD> |
|---|
| 473 | <TD WIDTH="10%"><B><I>Author(s)</I></B></TD> |
|---|
| 474 | <TD><B><I>Source code</I></B></TD> |
|---|
| 475 | <TD><B><I>Description</I></B></TD> |
|---|
| 476 | </TR> |
|---|
| 477 | END |
|---|
| 478 | } else { |
|---|
| 479 | print "Could not write to search output file\n"; |
|---|
| 480 | } |
|---|
| 481 | |
|---|
| 482 | my $name; |
|---|
| 483 | for $comp (sort(@comps)) { |
|---|
| 484 | # extract the scanned comp/instr name from lib, removing possible path |
|---|
| 485 | if ($comp =~ m/comp/i) { |
|---|
| 486 | ($name, $sec, $suf) = fileparse($comp, ".comp"); # without extension |
|---|
| 487 | } else { |
|---|
| 488 | ($name, $sec, $suf) = fileparse($comp, ".instr"); # without extension |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | $data = component_information($comp); |
|---|
| 492 | $data->{'path'} = $sec; |
|---|
| 493 | if (not defined($data)) { |
|---|
| 494 | print STDERR "mcdoc: Failed to get information for component/instrument '$comp'"; |
|---|
| 495 | } else { |
|---|
| 496 | print STDOUT "mcdoc: Search page adding $comp\n"; |
|---|
| 497 | } |
|---|
| 498 | if (!($sec =~ m/obsolete/i)) { |
|---|
| 499 | if ($sec =~ m/contrib/i) { |
|---|
| 500 | print "WARNING: This is a contributed $data->{'type'}. \n"; |
|---|
| 501 | } |
|---|
| 502 | add_comp_html($data, $filehandle, "$sec/$name", $comp); |
|---|
| 503 | } |
|---|
| 504 | } |
|---|
| 505 | if ($filehandle) { |
|---|
| 506 | print $filehandle <<END; |
|---|
| 507 | </TABLE> |
|---|
| 508 | END |
|---|
| 509 | } |
|---|
| 510 | } |
|---|
| 511 | |
|---|
| 512 | # Start of main =============================== |
|---|
| 513 | |
|---|
| 514 | my $index = 0; |
|---|
| 515 | my $file; |
|---|
| 516 | my $show_website = 0; |
|---|
| 517 | my $show_manual = 0; |
|---|
| 518 | my $show_compman = 0; |
|---|
| 519 | my $show_tutorial = 0; |
|---|
| 520 | |
|---|
| 521 | for($i = 0; $i < @ARGV; $i++) { |
|---|
| 522 | $_ = $ARGV[$i]; |
|---|
| 523 | # Options specific to mcdoc. |
|---|
| 524 | if(/^--show$/i || /^-s$/i || /^--html$/i) { |
|---|
| 525 | $browser = $MCSTAS::mcstas_config{'BROWSER'}; |
|---|
| 526 | } elsif(/^--text$/i || /^-t$/i) { |
|---|
| 527 | $browser = "text"; |
|---|
| 528 | } elsif(/^--web$/i || /^-w$/i) { |
|---|
| 529 | $show_website = 1; |
|---|
| 530 | } elsif(/^--manual$/i || /^-m$/i) { |
|---|
| 531 | $show_manual = 1; |
|---|
| 532 | } elsif(/^--comp$/i || /^-c$/i) { |
|---|
| 533 | $show_compman = 1; |
|---|
| 534 | } elsif(/^--tutorial$/i) { |
|---|
| 535 | $show_tutorial = 1; |
|---|
| 536 | } elsif(/^--local$/i) { |
|---|
| 537 | $use_local = 1; |
|---|
| 538 | } elsif(/^--force$/i || /^-f$/i) { |
|---|
| 539 | $is_forced = 1; |
|---|
| 540 | } elsif(/^--help$/i || /^-h$/i || /^-v$/i) { |
|---|
| 541 | print "Usage: mcdoc [options] <dir|file>\n"; |
|---|
| 542 | print "Generate/show component/instrument documentation using $browser\n"; |
|---|
| 543 | print " -f --force Force re-writting of existing HTML doc locally\n"; |
|---|
| 544 | print " -h --help Show this help\n"; |
|---|
| 545 | print " -l --tools Display the McStas tools list\n"; |
|---|
| 546 | print " -m --manual Open the McStas User manual\n"; |
|---|
| 547 | print " -c --comp Open the McStas Component manual\n"; |
|---|
| 548 | print " -t --text For single component, display as text\n"; |
|---|
| 549 | print " -w --web Open the McStas web page http://www.mcstas.org/\n"; |
|---|
| 550 | print " --tutorial Open the McStas tutorial from the local McStas library\n"; |
|---|
| 551 | print "SEE ALSO: mcstas, mcdoc, mcplot, mcrun, mcgui, mcresplot, mcstas2vitess\n"; |
|---|
| 552 | print "DOC: Please visit http://www.mcstas.org/\n"; |
|---|
| 553 | exit; |
|---|
| 554 | } elsif(/^--tools$/i || /^-l$/) { |
|---|
| 555 | print "McStas Tools\n"; |
|---|
| 556 | print " mcstas Main instrument compiler\n"; |
|---|
| 557 | print " mcrun Instrument maker and execution utility\n"; |
|---|
| 558 | print " mcgui Graphical User Interface instrument builder\n"; |
|---|
| 559 | print " mcdoc Component library documentation generator/viewer\n"; |
|---|
| 560 | print " mcplot Simulation result viewer\n"; |
|---|
| 561 | print " mcdisplay Instrument geometry viewer\n"; |
|---|
| 562 | print " mcresplot Instrument resolution function viewer\n"; |
|---|
| 563 | print " mcstas2vitess McStas to Vitess component translation utility\n"; |
|---|
| 564 | print " mcconvert Matlab <-> Scilab script conversion tool\n"; |
|---|
| 565 | print " mcformat Conversion tool for text files and MPI/grids\n"; |
|---|
| 566 | print " mcformatgui GUI for mcformat\n"; |
|---|
| 567 | print " mcdaemon Instrument results on-line plotting\n"; |
|---|
| 568 | print "When used with the -h flag, all tools display a specific help.\n"; |
|---|
| 569 | print "SEE ALSO: mcstas, mcdoc, mcplot, mcrun, mcgui, mcresplot, mcstas2vitess\n"; |
|---|
| 570 | print "DOC: Please visit http://www.mcstas.org/\n"; |
|---|
| 571 | exit; |
|---|
| 572 | } else { |
|---|
| 573 | $file = $ARGV[$i]; |
|---|
| 574 | $index++; |
|---|
| 575 | } |
|---|
| 576 | } # end for |
|---|
| 577 | |
|---|
| 578 | if ($show_website) { |
|---|
| 579 | # open the index.html |
|---|
| 580 | my $cmd = "$MCSTAS::mcstas_config{'BROWSER'} http://www.mcstas.org/ "; |
|---|
| 581 | print "mcdoc: Starting $cmd\n"; system("$cmd\n"); |
|---|
| 582 | die "mcdoc: web site done.\n"; |
|---|
| 583 | } |
|---|
| 584 | |
|---|
| 585 | if ($show_manual) { |
|---|
| 586 | # open the manual using embedded acroread plugin |
|---|
| 587 | $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $HTTP_SYSDIR/doc/mcstas-manual.pdf"; |
|---|
| 588 | print "mcdoc: Starting $cmd\n"; system("$cmd\n"); |
|---|
| 589 | die "mcdoc: User manual done.\n"; |
|---|
| 590 | } |
|---|
| 591 | |
|---|
| 592 | if ($show_compman) { |
|---|
| 593 | # open the component manual |
|---|
| 594 | $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $HTTP_SYSDIR/doc/mcstas-components.pdf"; |
|---|
| 595 | print "mcdoc: Starting $cmd\n"; system("$cmd\n"); |
|---|
| 596 | die "mcdoc: Component manual done.\n"; |
|---|
| 597 | } |
|---|
| 598 | |
|---|
| 599 | if ($show_tutorial) { |
|---|
| 600 | # open the index.html |
|---|
| 601 | $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $HTTP_SYSDIR/doc/tutorial/html/tutorial.html"; |
|---|
| 602 | print "mcdoc: Starting $cmd\n"; system("$cmd\n"); |
|---|
| 603 | die "mcdoc: Tutorial done.\n"; |
|---|
| 604 | } |
|---|
| 605 | |
|---|
| 606 | # if 'file' is given |
|---|
| 607 | if ($index > 0) { |
|---|
| 608 | if (-d $file) { $lib_dir = $file; } # get doc of the given dir |
|---|
| 609 | else { $is_single_file=1; $single_comp_name = $file; } # search locally and in lib |
|---|
| 610 | $use_local=1; # will also search locally |
|---|
| 611 | } |
|---|
| 612 | |
|---|
| 613 | my $filehandle = 0; |
|---|
| 614 | my @sections; |
|---|
| 615 | my %section_headers; |
|---|
| 616 | |
|---|
| 617 | if (not $is_single_file) { |
|---|
| 618 | # Open the local documentation file |
|---|
| 619 | $filehandle = new FileHandle; |
|---|
| 620 | my $no_lib_write = 0; |
|---|
| 621 | |
|---|
| 622 | if (not open($filehandle, ">$lib_dir/$out_file")) { $no_lib_write = 1; } |
|---|
| 623 | if ($no_lib_write) { |
|---|
| 624 | my $no_local_write = 0; |
|---|
| 625 | if (not open($filehandle, ">$out_file")) { $no_local_write = 1; } |
|---|
| 626 | if ($no_local_write) { |
|---|
| 627 | $filehandle = 0; # will not write the catalog |
|---|
| 628 | print STDERR "mcdoc: Could not open $out_file for writing.\n"; |
|---|
| 629 | } |
|---|
| 630 | } else { |
|---|
| 631 | $out_file = "$lib_dir/$out_file"; |
|---|
| 632 | } |
|---|
| 633 | if (not $filehandle) { |
|---|
| 634 | if (-f "$lib_dir/$out_file") { |
|---|
| 635 | $out_file = "$lib_dir/$out_file"; |
|---|
| 636 | } |
|---|
| 637 | elsif (not -f $out_file) { |
|---|
| 638 | print STDERR "mcdoc: Could not find the $out_file library catalog.\n"; |
|---|
| 639 | } |
|---|
| 640 | } |
|---|
| 641 | } |
|---|
| 642 | |
|---|
| 643 | if ($use_local) { |
|---|
| 644 | # define local and lib sections |
|---|
| 645 | @sections = ("sources", "optics", "samples", "monitors", |
|---|
| 646 | "misc", "contrib", "obsolete","examples","local","data","share","doc"); |
|---|
| 647 | %section_headers = |
|---|
| 648 | ("sources" => '<B><FONT COLOR="#FF0000">Sources</FONT></B>', |
|---|
| 649 | "optics" => '<B><FONT COLOR="#FF0000">Optics</FONT></B>', |
|---|
| 650 | "samples" => '<B><FONT COLOR="#FF0000">Samples</FONT></B>', |
|---|
| 651 | "monitors" => '<B><FONT COLOR="#FF0000">Detectors</FONT> and monitors</B>', |
|---|
| 652 | "contrib" => '<B><FONT COLOR="#FF0000">Contributed</FONT> components</B>', |
|---|
| 653 | "misc" => '<B><FONT COLOR="#FF0000">Misc</FONT></B>', |
|---|
| 654 | "obsolete" => '<B><FONT COLOR="#FF0000">Obsolete</FONT> (avoid usage whenever possible)</B>', |
|---|
| 655 | "examples" => '<B><FONT COLOR="#FF0000">Instrument Examples</FONT></B>', |
|---|
| 656 | "local" => '<B><FONT COLOR="#FF0000">Local components</FONT></B>', |
|---|
| 657 | "data" => '<B><FONT COLOR="#FF0000">Data files</FONT></B>', |
|---|
| 658 | "share" => '<B><FONT COLOR="#FF0000">Shared libraries</FONT></B>', |
|---|
| 659 | "doc" => '<B><FONT COLOR="#FF0000">Documentation</FONT></B>'); |
|---|
| 660 | } else { |
|---|
| 661 | # define lib sections |
|---|
| 662 | @sections = ("sources", "optics", "samples", "monitors", "misc", "contrib","examples"); |
|---|
| 663 | %section_headers = |
|---|
| 664 | ("sources" => '<B><FONT COLOR="#FF0000">Sources</FONT></B>', |
|---|
| 665 | "optics" => '<B><FONT COLOR="#FF0000">Optics</FONT></B>', |
|---|
| 666 | "samples" => '<B><FONT COLOR="#FF0000">Samples</FONT></B>', |
|---|
| 667 | "monitors" => '<B><FONT COLOR="#FF0000">Detectors</FONT> and monitors</B>', |
|---|
| 668 | "contrib" => '<B><FONT COLOR="#FF0000">Contributed</FONT> components</B>', |
|---|
| 669 | "misc" => '<B><FONT COLOR="#FF0000">Misc</FONT></B>', |
|---|
| 670 | "obsolete" => '<B><FONT COLOR="#FF0000">Obsolete</FONT> (avoid usage whenever possible)</B>', |
|---|
| 671 | "examples" => '<B><FONT COLOR="#FF0000">Instrument Examples</FONT></B>',); |
|---|
| 672 | } |
|---|
| 673 | my @tblist = map "<A href=\"#$_\">$_</A>", @sections; |
|---|
| 674 | my $toolbar = "<P ALIGN=CENTER>\n [ " . join("\n | ", @tblist) . " ]\n</P>\n"; |
|---|
| 675 | $toolbar .= "<P ALIGN=CENTER>\n [ <a href=\"$HTTP_SYSDIR/doc/mcstas-manual.pdf\">User Manual</a> |
|---|
| 676 | | <a href=\"$HTTP_SYSDIR/doc/mcstas-components.pdf\">Component Manual</a> |
|---|
| 677 | | <a href=\"$HTTP_SYSDIR/doc/tutorial/html/tutorial.html\">McStas tutorial</a> |
|---|
| 678 | | <a href=\"$HTTP_SYSDIR/data\">Data files</a> ]\n</P>\n"; |
|---|
| 679 | |
|---|
| 680 | if ($filehandle) { |
|---|
| 681 | html_main_start($filehandle, $toolbar); |
|---|
| 682 | } |
|---|
| 683 | # open each section, look for comps, add entry in index.html, |
|---|
| 684 | # and generate comp doc |
|---|
| 685 | my $sec; |
|---|
| 686 | my $is_forced_orig = $is_forced; |
|---|
| 687 | for $sec (@sections) { |
|---|
| 688 | add_comp_section_html($lib_dir, $sec, $section_headers{$sec}, $filehandle); |
|---|
| 689 | $is_forced = $is_forced_orig; # may have been changed globally (sec == local) |
|---|
| 690 | } |
|---|
| 691 | if ($filehandle) { |
|---|
| 692 | html_main_end($filehandle, $toolbar); |
|---|
| 693 | close($filehandle); |
|---|
| 694 | } |
|---|
| 695 | |
|---|
| 696 | if (-f $out_file) { |
|---|
| 697 | if ($browser ne "text") { |
|---|
| 698 | # In case of multiple matches, create table of results: |
|---|
| 699 | if (@valid_names > 1) { |
|---|
| 700 | require File::Temp; |
|---|
| 701 | my $searchfile; |
|---|
| 702 | ($filehandle, $searchfile) = File::Temp::tempfile("McDoc_XXXX", SUFFIX => '.html'); |
|---|
| 703 | open($filehandle, ">$searchfile") || die "Could not write to search output file\n"; |
|---|
| 704 | add_comp_search_html($file, $filehandle, @valid_names); |
|---|
| 705 | html_main_end($filehandle, $toolbar); |
|---|
| 706 | close($filehandle); |
|---|
| 707 | $out_file = "$searchfile"; |
|---|
| 708 | } |
|---|
| 709 | |
|---|
| 710 | # open the index.html |
|---|
| 711 | my $cmd = "$MCSTAS::mcstas_config{'BROWSER'} $out_file"; |
|---|
| 712 | print "mcdoc: Starting $cmd\n"; system("$cmd\n"); |
|---|
| 713 | } |
|---|
| 714 | } |
|---|