1#!perl -w 2# $Id: make_issues.pl,v 1.3 2004/09/30 16:09:27 jlinoff Exp $ 3# ================================================ 4# Copyright Notice 5# Copyright (C) 1998-2004 by Joe Linoff (http://www.joelinoff.com) 6# 7# Permission is hereby granted, free of charge, to any person obtaining 8# a copy of this software and associated documentation files (the 9# "Software"), to deal in the Software without restriction, including 10# without limitation the rights to use, copy, modify, merge, publish, 11# distribute, sublicense, and/or sell copies of the Software, and to 12# permit persons to whom the Software is furnished to do so, subject to 13# the following conditions: 14# 15# The above copyright notice and this permission notice shall be 16# included in all copies or substantial portions of the Software. 17# 18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21# IN NO EVENT SHALL JOE LINOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24# OTHER DEALINGS IN THE SOFTWARE. 25# 26# Comments and suggestions are always welcome. 27# ================================================ 28# 29# Generate an HTML FAQ by parsing a text file 30# with some embedded keywords. 31# 32# This script recognizes certain keywords. 33# 34# All keywords must start at the beginning of a line. 35# 36# Comments are delimited by # at the beginning of 37# a line unless you are in a description subsection. 38# 39# The document contains two parts, the page section 40# and the entry sections. The page section describes 41# details about the document itself. The page keywords 42# have the PAGE_ prefix. 43# 44# There is an entry section for each entry in the 45# document. The entry keywords have the ENTRY_ prefix. 46# 47# Here is what an example document might look like 48# with two entries. 49# 50# # ======================== 51# # This is an example list 52# # of issues. 53# # ======================== 54# PAGE_TITLE: Example List 55# PAGE_AUTHOR: I.M. Author 56# PAGE_EMAIL: imauthor@mail.net 57# PAGE_REVISION: $Revision: 1.3 $ 58# PAGE_DATE: $Date: 2004/09/30 16:09:27 $ 59# PAGE_DESC_BEGIN: 60# This page keeps track of issues. 61# If is used for a variety of purposes. 62# PAGE_DESC_END: 63# 64# # ======================== 65# # Entry 0001 66# # ======================== 67# ENTRY_ID: 0001 68# ENTRY_TITLE: There is a bug in the foo stuff. 69# ENTRY_REPORTED_BY: I.M. Author 70# ENTRY_REPORTED_ON: 2002/07/29 71# ENTRY_STATUS: FIXED 72# ENTRY_RESOLVED_BY: I.M Author 73# ENTRY_RESOLVED_ON: 2002/07/29 74# ENTRY_REPORTED_BEGIN: 75# There is a bug. 76# ENTRY_REPORTED_END: 77# ENTRY_RESOLVED_BEGIN: 78# It was fixed in release 10. 79# ENTRY_RESOLVED_END: 80# 81# # ======================== 82# # Entry 0002 83# # ======================== 84# ENTRY_ID: 0002 85# ENTRY_TITLE: There is another bug in the foo stuff. 86# ENTRY_REPORTED_BY: I.M. Author 87# ENTRY_REPORTED_ON: 2002/07/29 88# ENTRY_STATUS: OPEN 89# ENTRY_RESOLVED_BY: 90# ENTRY_RESOLVED_ON: 91# ENTRY_REPORTED_BEGIN: 92# There is another bug. 93# ENTRY_REPORTED_END: 94# ENTRY_RESOLVED_BEGIN: 95# ENTRY_RESOLVED_END: 96# 97# The keywords are described in more detail in the following 98# sections. 99# 100# ================================================ 101# PAGE_TITLE: <title> 102# 103# The title of the page. The keyword and data must exist on one 104# line. 105# 106# Here is a usage example: 107# PAGE_TITLE: <a href="http://foobar.com">The Title</a> 108# 109# Note that the FAQER will strip out the HTML tags for the page 110# <title></title> entry so that wierd stuff will not show up at the 111# top of the browser window. 112# 113# ================================================ 114# PAGE_AUTHOR: <name> 115# 116# The author of the page. The keyword and data must exist on one 117# line. 118# 119# Here is a sample usage: 120# PAGE_AUTHOR: Joe Linoff 121# 122# ================================================ 123# PAGE_EMAIL: <email address> 124# 125# The e-mail address of the author. The keyword and data must 126# exist on one line. 127# 128# Here is a sample usage: 129# PAGE_EMAIL: jdl@xilinx.com 130# 131# ================================================ 132# PAGE_REVISION: <date> 133# 134# The page revision. The keyword and data must exist on one 135# line. 136# 137# Here is a sample usage: 138# PAGE_REVISION: $Revision: 1.3 $ 139# 140# ================================================ 141# PAGE_DATE: <date> 142# 143# The Date this page was generated. The keyword and data must 144# exist on one line. 145# 146# Here is a sample usage: 147# PAGE_DATE: $Date: 2004/09/30 16:09:27 $ 148# 149# ================================================ 150# PAGE_DESC_BEGIN: 151# <lines> 152# PAGE_DESC_END: 153# 154# A description of the title page. 155# 156# The desccription can contain any text, including HTML. 157# Remember that if you want <,> or & characters 158# you must use <, > or & 159# 160# Here is an example usage: 161# PAGE_DESC_BEGIN: 162# This is a the page of issues. 163# PAGE_DESC_END: 164# 165# ================================================ 166# ENTRY_ID: <id> 167# 168# This describes a unique entry id. I use numbers but this can be 169# anything. The script verifies that each entry id is unique. The 170# keyword and data must exist on one line. 171# 172# Here is an example usage: 173# ENTRY_ID: 0001 174# 175# ================================================ 176# ENTRY_TITLE: <title> 177# 178# This describes the entry title. The keyword and data must exist 179# on one line. 180# 181# Here is an example usage: 182# ENTRY_TITLE: Core dump in foo when -aa 100 is specified. 183# 184# ================================================ 185# ENTRY_REPORTED_BY: <name> 186# 187# This describes the author of the entry. This is usually 188# the person who reported it. I sometimes embed the 189# the email information. The keyword and data must exist 190# on one line. 191# 192# Here is an example usage: 193# ENTRY_REPORTED_BY: <a href="mailto:jdl@xilinx.com">Joe</a> 194# 195# ================================================ 196# ENTRY_REPORTED_ON: <date> 197# 198# This describes the date that the entry was reported. The keyword 199# and data must exist on one line. 200# 201# Here is an example usage: 202# ENTRY_REPORTED_BY: <a href="mailto:jdl@xilinx.com">Joe</a> 203# 204# ================================================ 205# ENTRY_STATUS: <string> 206# 207# The entry status. The user can specify any string but it is best 208# if it has no white space because it is used to generate 209# additional HTML files. I typically use statuses like: OPEN, 210# FIXED, CLOSED, PENDING. When the script runs it groups entries 211# based on the status string (the entries are case sensitive) and 212# generates HTML files with names like issues_OPEN.html and 213# issues_FIXED.html. I use upper case to avoid problems. The 214# keyword and data must exist on one line. 215# 216# Here is an example usage: 217# ENTRY_STATUS: OPEN 218# 219# ================================================ 220# ENTRY_RESOLVED_BY: <name> 221# 222# This describes the author of the entry. This is usually 223# the person who resolved it. I sometimes embed the 224# the email information. The keyword and data must exist 225# on one line. 226# 227# Here is an example usage: 228# ENTRY_RESOLVED_BY: <a href="mailto:jdl@xilinx.com">Joe</a> 229# 230# ================================================ 231# ENTRY_RESOLVED_ON: <date> 232# 233# This describes the date that the entry was resolved. The keyword 234# and data must exist on one line. 235# 236# Here is an example usage: 237# ENTRY_RESOLVED_BY: <a href="mailto:jdl@xilinx.com">Joe</a> 238# 239# ================================================ 240# ENTRY_REPORTED_BEGIN: 241# <lines> 242# ENTRY_REPORTED_END: 243# 244# A description of the entry. 245# 246# The desccription can contain any text, including HTML. 247# Remember that if you want <,> or & characters 248# you must use <, > or & 249# 250# Here is an example usage: 251# ENTRY_REPORTED_BEGIN: 252# There is a problem. 253# ENTRY_REPORTED_END: 254# 255# ================================================ 256# ENTRY_RESOLVED_BEGIN: 257# <lines> 258# ENTRY_RESOLVED_END: 259# 260# A description of the resolution. 261# 262# The desccription can contain any text, including HTML. 263# Remember that if you want <,> or & characters 264# you must use <, > or & 265# 266# Here is an example usage: 267# ENTRY_RESOLVED_BEGIN: 268# This entry was resolved by fixing the problem. 269# ENTRY_RESOLVED_END: 270# 271# 272use strict; 273 274&Main; 275 276# ================================================================ 277# MAIN 278# ================================================================ 279sub Main 280{ 281 my $ifile = ""; 282 my $ofile = ""; 283 my $verbose = 0; 284 while ( $#ARGV>=0 ) { 285 my $arg = shift @ARGV; 286 if ( $arg eq "-i" ) { 287 $ifile = shift @ARGV; 288 next; 289 } 290 if ( $arg eq "-o" ) { 291 $ofile = shift @ARGV; 292 next; 293 } 294 if ( $arg eq "-h" ) { 295 &Usage; 296 } 297 if ( $arg eq "-v" ) { 298 $verbose = 1; 299 next; 300 } 301 print STDERR "ERROR: Unrecognized switch '$arg'.\n"; 302 &Usage; 303 } 304 if ( $ifile eq "" ) { 305 print STDERR "ERROR: -i <file> not specified.\n"; 306 &Usage; 307 } 308 if ( $ofile eq "" ) { 309 print STDERR "ERROR: -o <file> not specified.\n"; 310 &Usage; 311 } 312 &Process($ifile,$ofile); 313} 314# ================================================================ 315# Process the data and create the HTML output. 316# ================================================================ 317sub Process 318{ 319 my $ifile = shift; 320 my $ofile = shift; 321 322 # ================================================ 323 # Set the default page records. 324 # ================================================ 325 my %page = (); 326 $page{"title"} = "Unknown"; 327 $page{"author"} = "Unknown"; 328 $page{"email"} = ""; 329 $page{"revision"} = "Unknown"; 330 $page{"date"} = "Unknown"; 331 $page{"description"} = "Unknown"; 332 333 # ================================================ 334 # Process the input file. 335 # ================================================ 336 my %entry = (); 337 my %status = (); 338 my $num_entries = 0; 339 my $entryid = ""; 340 my $err = 0; 341 my $lineno = 1; 342 open(IFILE,"$ifile") || die "ERROR: Can't read '$ifile'.\n"; 343 while(<IFILE>) { 344 $lineno++; 345 chop; 346 my $line = $_; 347 if ( $line =~ /^PAGE_TITLE:\s+(.*)$/ ) { 348 $page{"title"} = $1; 349 next; 350 } 351 if ( $line =~ /^PAGE_AUTHOR:\s+(.*)$/ ) { 352 $page{"author"} = $1; 353 next; 354 } 355 if ( $line =~ /^PAGE_EMAIL:\s+(.*)$/ ) { 356 $page{"email"} = $1; 357 next; 358 } 359 if ( $line =~ /^PAGE_REVISION:\s+(.*)$/ ) { 360 $page{"revision"} = $1; 361 next; 362 } 363 if ( $line =~ /^PAGE_DATE:\s+(.*)$/ ) { 364 $page{"date"} = $1; 365 next; 366 } 367 if ( $line =~ /^PAGE_DESC_BEGIN:\s*$/ ) { 368 my $desc = ""; 369 while(<IFILE>) { 370 chop; 371 $line = $_; 372 last if ( $line =~ /^PAGE_DESC_END:\s*$/ ); 373 $desc = "$desc\n$line"; 374 } 375 $page{"description"} = $desc; 376 next; 377 } 378 if ( $line =~ /^ENTRY_ID:\s+(.*)$/ ) { 379 $num_entries++; 380 $entryid = $1; 381 if ( defined $entry{$entryid} ) { 382 print STDERR "ERROR: Duplicate entry id '$entryid' found at line $lineno.\n"; 383 $err++; 384 } 385 $entry{$entryid}{"title"} = ""; 386 $entry{$entryid}{"reported_by"} = ""; 387 $entry{$entryid}{"reported_on"} = ""; 388 $entry{$entryid}{"reported_description"} = ""; 389 $entry{$entryid}{"status"} = ""; 390 $entry{$entryid}{"resolved_by"} = ""; 391 $entry{$entryid}{"resolved_on"} = ""; 392 $entry{$entryid}{"resolved_description"} = ""; 393 next; 394 } 395 if ( $line =~ /^ENTRY_TITLE:\s+(.*)$/ ) { 396 $entry{$entryid}{"title"} = $1; 397 next; 398 } 399 if ( $line =~ /^ENTRY_REPORTED_BY:\s+(.*)$/ ) { 400 $entry{$entryid}{"reported_by"} = $1; 401 next; 402 } 403 if ( $line =~ /^ENTRY_REPORTED_ON:\s+(.*)$/ ) { 404 $entry{$entryid}{"reported_on"} = $1; 405 next; 406 } 407 if ( $line =~ /^ENTRY_STATUS:\s*(.*)$/ ) { 408 $entry{$entryid}{"status"} = $1; 409 if ( $1 ne "" ) { 410 if ( ! defined( $status{$1} ) ) { 411 $status{$1} = 0; 412 } 413 my $x = $status{$1}; 414 my $y = $x + 1; 415 $status{$1} = $y; 416 } 417 next; 418 } 419 if ( $line =~ /^ENTRY_RESOLVED_BY:\s*(.*)$/ ) { 420 $entry{$entryid}{"resolved_by"} = $1; 421 next; 422 } 423 if ( $line =~ /^ENTRY_RESOLVED_ON:\s*(.*)$/ ) { 424 $entry{$entryid}{"resolved_on"} = $1; 425 next; 426 } 427 if ( $line =~ /^ENTRY_REPORTED_BEGIN:\s*$/ ) { 428 my $desc = ""; 429 while(<IFILE>) { 430 chop; 431 $line = $_; 432 last if ( $line =~ /^ENTRY_REPORTED_END:\s*$/ ); 433 if ( $line =~ /^ENTRY_LINK:\s*(\S*)\s+(.*)$/ ) { 434 # ENTRY_LINK: <id> <desc> 435 $desc = "$desc\n<a href=#TAG_$1>$2</a>"; 436 } 437 else { 438 $desc = "$desc\n$line"; 439 } 440 } 441 $entry{$entryid}{"reported_description"} = $desc; 442 next; 443 } 444 if ( $line =~ /^ENTRY_RESOLVED_BEGIN:\s*$/ ) { 445 my $desc = ""; 446 while(<IFILE>) { 447 chop; 448 $line = $_; 449 last if ( $line =~ /^ENTRY_RESOLVED_END:\s*$/ ); 450 if ( $line =~ /^ENTRY_LINK:\s*(\S*)\s+(.*)$/ ) { 451 # ENTRY_LINK: <id> <desc> 452 $desc = "$desc\n<a href=#TAG_$1>$2</a>"; 453 } 454 else { 455 $desc = "$desc\n$line"; 456 } 457 } 458 $entry{$entryid}{"resolved_description"} = $desc; 459 next; 460 } 461 if ( $line =~ /^(ENTRY\S+:)/ ) { 462 print STDERR "ERROR: Unrecognized token '$1' at line $lineno\n"; 463 $err++; 464 next; 465 } 466 if ( $line =~ /^(PAGE\S+:)/ ) { 467 print STDERR "ERROR: Unrecognized token '$1' at line $lineno\n"; 468 $err++; 469 next; 470 } 471 } 472 close(IFILE); 473 474 exit $err if ( $err ); 475 476 # ================================================ 477 # Write the master page. 478 # ================================================ 479 my @tokens = split(/\./,$ofile); 480 my $rootfn = $tokens[0]; 481 my $rootext = $tokens[1]; 482 my $sumfile = "${rootfn}-summary.html"; 483 print "Creating $ofile ...\n"; 484 open(OFILE,">$ofile") || die "ERROR: Can't write '$ofile'.\n"; 485 # Create the header 486 &PrintHtmlHeader(\*OFILE, 487 "$page{title}", 488 "All", 489 "$page{author}", 490 "$page{date}", 491 "$page{revision}", 492 "Summary", 493 "$sumfile"); 494 print OFILE "$page{description}\n"; 495 # Create the summary table. 496 &PrintHtmlStatusTable(\*OFILE, 497 \%status, 498 $num_entries, 499 $ofile, 500 "$rootfn", 501 "$rootext"); 502 # entry summary table 503 &PrintHtmlEntrySummaryTable(\*OFILE, 504 \%entry, 505 "all", 506 ""); 507 # Entries 508 &PrintHtmlEntries(\*OFILE, 509 \%entry, 510 "all"); 511 # End of the file. 512 &PrintHtmlTrailer(\*OFILE, 513 "$page{email}", 514 "$page{author}", 515 "$page{date}"); 516 # write the master output file. 517 close OFILE; 518 519 # ================================================ 520 # Write the summary page. 521 # ================================================ 522 print "Creating $sumfile ...\n"; 523 open(OFILE,">$sumfile") || die "ERROR: Can't write '$sumfile'.\n"; 524 # Create the header 525 &PrintHtmlHeader(\*OFILE, 526 "$page{title}", 527 "Summary", 528 "$page{author}", 529 "$page{date}", 530 "$page{revision}", 531 "All", 532 "$ofile"); 533 # Create the summary table. 534 &PrintHtmlStatusTable(\*OFILE, 535 \%status, 536 $num_entries, 537 $sumfile, 538 "$rootfn", 539 "$rootext"); 540 # entry summary table 541 &PrintHtmlEntrySummaryTable(\*OFILE, 542 \%entry, 543 "all", 544 "$tokens[0].html"); 545 # End of the file. 546 &PrintHtmlTrailer(\*OFILE, 547 "$page{email}", 548 "$page{author}", 549 "$page{date}"); 550 # write the master output file. 551 close OFILE; 552 553 # ================================================ 554 # Write pages for each status. 555 # ================================================ 556 my $key; 557 foreach $key ( sort keys %status ) { 558 my $fn = "${rootfn}_$key.${rootext}"; 559 print "Creating $fn ...\n"; 560 open(OFILE,">$fn") || die "ERROR: Can't write '$fn'.\n"; 561 # Create the header 562 &PrintHtmlHeader(\*OFILE, 563 "$page{title}", 564 "$key Status", 565 "$page{author}", 566 "$page{date}", 567 "$page{revision}", 568 "All", 569 $ofile, 570 "$rootfn", 571 "$rootext"); 572 # entry summary table 573 &PrintHtmlEntrySummaryTable(\*OFILE, 574 \%entry, 575 $key, 576 ""); 577 # Entries 578 &PrintHtmlEntries(\*OFILE, 579 \%entry, 580 $key); 581 # End of the file. 582 &PrintHtmlTrailer(\*OFILE, 583 "$page{email}", 584 "$page{author}", 585 "$page{date}"); 586 # write the master output file. 587 close OFILE; 588 } 589} 590# ================================================================ 591# Print the header 592# ================================================================ 593sub PrintHtmlHeader 594{ 595 my $out = shift; 596 my $title = shift; 597 my $subtitle = shift; 598 my $author = shift; 599 my $date = shift; 600 my $revision = shift; 601 my $link = shift; 602 my $href = shift; 603 604 print $out "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"; 605 print $out "<!-- Subroutine: PrintHtmlHeader -->\n"; 606 print $out "<html>\n"; 607 print $out "<head>\n"; 608 609 if( $title =~ /\<\/a>/ ) { 610 # Strip out the formatting tags for the title. 611 my $tmp = $title; 612 while ( $tmp =~ /<[^>]+>/ ) { 613 $tmp =~ s/<[^>]+>/ /g; 614 } 615 print $out "<title>${tmp}</title>\n"; 616 } 617 else { 618 print $out "<title>${title}</title>\n"; 619 } 620 621 print $out "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n"; 622 print $out "</head>\n"; 623 print $out "<body bgcolor=white>\n"; 624 print $out "<a name=top></a>\n"; 625 print $out "<center>\n"; 626 627 print $out "<font size=\"+2\"><b>${title}</b></font>"; 628 print $out "<br><font size=\"+2\"><b>${subtitle}</b></font>"; 629 if( $link ne "" && $href ne "" ) { 630 print $out "<br><b><a href=\"${href}\">${link}</a></b>\n"; 631 } 632 633 print $out "<br>\n"; 634 print $out "${author}\n"; 635 print $out "<br>\n"; 636 print $out "${date}\n"; 637 print $out "<br>\n"; 638 print $out "<font size=\"-1\">${revision}</font>\n"; 639 print $out "</center>\n"; 640} 641# ================================================================ 642# Print the header 643# ================================================================ 644sub PrintHtmlTrailer 645{ 646 my $out = shift; 647 my $email = shift; 648 my $author = shift; 649 my $date = shift; 650 651 print $out "<!-- Subroutine: PrintHtmlTrailer -->\n"; 652 print $out "<hr noshade width=\"100%\" size=2>\n"; 653 print $out "<center>\n"; 654 print $out "<font size=\"-1\">\n"; 655 print $out "<a href=\"#top\">[Top]</a>\n"; 656 print $out "<br>\n"; 657 print $out "This page is maintained by <a href=\"mailto:${email}\">${author}</a>.\n"; 658 print $out "<br>\n"; 659 print $out "Last updated: ${date}\n"; 660 print $out "<br>\n"; 661 print $out "<br>\n"; 662 print $out "<i>This page was automatically generated by issues.pl.</i>\n"; 663 print $out "</font>\n"; 664 print $out "</center>\n"; 665 print $out "</body>\n"; 666 print $out "</html>\n"; 667} 668# ================================================================ 669# Status summary table. 670# ================================================================ 671sub PrintHtmlStatusTable 672{ 673 my $out = shift; 674 my $ht = shift; 675 my $num_entries = shift; 676 my $ofile = shift; 677 my $rootfn = shift; 678 my $rootext = shift; 679 680 my %status = %$ht; 681 my $key; 682 683 print $out "<!-- Subroutine: PrintHtmlStatusTable -->\n"; 684 print $out "<hr noshade width=\"100%\" size=2>\n"; 685 print $out "<center>\n"; 686 print $out "<font size=\"+1\">Status Summary</font><br>\n"; 687 print $out "<table border=1>\n"; 688 print $out "<tr>\n"; 689 print $out "<th>Status\n"; 690 print $out "<th>Number\n"; 691 foreach $key ( sort keys %status ) { 692 my $fn = "${rootfn}_$key.${rootext}"; 693 print $out "</tr>\n"; 694 print $out "<tr>\n"; 695 print $out "<td><a href=\"$fn\">$key</a></td>\n"; 696 print $out "<td align=right>$status{$key}</td>\n"; 697 } 698 print $out "</tr>\n"; 699 print $out "<tr>\n"; 700 print $out "<td><b>Total</b></td>\n"; 701 print $out "<td align=right>$num_entries</td>\n"; 702 print $out "</tr>\n"; 703 print $out "</table>\n"; 704 print $out "</center>\n"; 705} 706# ================================================================ 707# Entry summary table. 708# ================================================================ 709sub PrintHtmlEntrySummaryTable 710{ 711 my $out = shift; 712 my $ht = shift; 713 my $match = shift; 714 my $href_prefix = shift; 715 716 my %entry = %$ht; 717 my $key; 718 719 print $out "<!-- Subroutine: PrintHtmlEntrySummaryTable -->\n"; 720 print $out "<a name=summary></a>\n"; 721 print $out "<hr noshade width=\"100%\" size=2>\n"; 722 print $out "<center>\n"; 723 print $out "<font size=\"+1\">Entry Summary</font><br>\n"; 724 print $out "<table border=1>\n"; 725 print $out "<tr>\n"; 726 print $out "<th>Id\n"; 727 print $out "<th>Title\n"; 728 print $out "<th>Status\n"; 729 foreach $key ( sort keys %entry ) { 730 my $status = $entry{$key}{status}; 731 next if( $status ne $match && $match ne "all" ); 732 print $out "</tr>\n"; 733 print $out "<tr>\n"; 734 print $out "<td><a href=\"${href_prefix}#TAG_$key\">$key</a></td>\n"; 735 print $out "<td>$entry{$key}{title}</td>\n"; 736 print $out "<td>$entry{$key}{status}</td>\n"; 737 } 738 print $out "</tr>\n"; 739 print $out "</table>\n"; 740 print $out "</center>\n"; 741} 742# ================================================================ 743# Entries 744# ================================================================ 745sub PrintHtmlEntries 746{ 747 my $out = shift; 748 my $ht = shift; 749 my $match = shift; 750 751 my %entry = %$ht; 752 my $key; 753 my @xkeys = sort keys %entry; 754 my @keys = (); 755 foreach $key ( @xkeys ) { 756 my $status = $entry{$key}{status}; 757 next if( $status ne $match && $match ne "all" ); 758 push @keys,$key; 759 } 760 my $previous = ""; 761 my $next = ""; 762 my $i = 0; 763 foreach $key ( @keys ) { 764 $i++; 765 $previous = ""; 766 $previous = $keys[$i-2] if($i-2>=0); 767 $next = ""; 768 $next = $keys[$i] if($i<=$#keys); 769 &PrintHtmlEntry($out,$ht,$key,$next,$previous); 770 } 771} 772# ================================================================ 773# Entries 774# ================================================================ 775sub PrintHtmlEntry 776{ 777 my $out = shift; 778 my $ht = shift; 779 my $key = shift; 780 my $next = shift; 781 my $previous = shift; 782 783 my %entry = %$ht; 784 785 print $out "<!-- Subroutine: PrintHtmlEntry -->\n"; 786 print $out "<a name=TAG_$key></a>\n"; 787 print $out "<hr noshade width=\"100%\" size=2>\n"; 788 789 print $out "<table width=\"100%\" border=0 cellspacing=0 cellpadding=0>\n"; 790 print $out "<tr valign=top>\n"; 791 print $out "<td>\n"; 792 793 print $out "<table border=0 cellspacing=0 cellpadding=0>\n"; 794 print $out "<tr><td><b>Title: </b></td><td>$entry{$key}{title}</td></tr>\n"; 795 print $out "<tr><td><b>Status: </b></td><td>$entry{$key}{status}</td></tr>\n"; 796 print $out "<tr><td><b>Reported By: </b></td><td>$entry{$key}{reported_by}</td></tr>\n"; 797 print $out "<tr><td><b>Reported On: </b></td><td>$entry{$key}{reported_on}</td></tr>\n"; 798 print $out "<tr><td><b>Resolved By: </b></td><td>$entry{$key}{resolved_by}</td></tr>\n"; 799 print $out "<tr><td><b>Resolved On: </b></td><td>$entry{$key}{resolved_on}</td></tr>\n"; 800 print $out "</table>\n"; 801 print $out "</td>\n"; 802 803 print $out "<td align=right>\n"; 804 print $out "<b>Id: </b>$key\n"; 805 print $out "<br>\n"; 806 print $out "<font size=\"-1\"><a href=\"#top\">[Top]</a></font>\n"; 807 print $out "<br>\n"; 808 print $out "<font size=\"-1\"><a href=\"#summary\">[Summary]</a></font>\n"; 809 if ( $next ne "" ) { 810 print $out "<br>\n"; 811 print $out "<font size=\"-1\"><a href=\"#TAG_$next\">[Next]</a></font>\n"; 812 } 813 if ( $previous ne "" ) { 814 print $out "<br>\n"; 815 print $out "<font size=\"-1\"><a href=\"#TAG_$previous\">[Previous]</a></font>\n"; 816 } 817 818 print $out "</td>\n"; 819 print $out "</tr>\n"; 820 print $out "</table>"; 821 822 print $out "<b>Problem Description: </b>\n"; 823 print $out "<blockquote>\n"; 824 print $out "$entry{$key}{reported_description}\n"; 825 print $out "</blockquote>\n"; 826 827 print $out "<b>Solution Description: </b>\n"; 828 print $out "<blockquote>\n"; 829 print $out "$entry{$key}{resolved_description}\n"; 830 print $out "</blockquote>\n"; 831} 832# ================================================================ 833# Report the usage and exit. 834# ================================================================ 835sub Usage 836{ 837 my $rev = '$Id: make_issues.pl,v 1.3 2004/09/30 16:09:27 jlinoff Exp $'; #' 838 print STDERR "\n"; 839 print STDERR "$rev\n"; 840 print STDERR "\n"; 841 print STDERR "usage: perl issues.pl [args]\n"; 842 print STDERR "\n"; 843 print STDERR " -h On-line help.\n"; 844 print STDERR " -i <file> The input file\n"; 845 print STDERR " -o <file> The output HTML file\n"; 846 print STDERR " -v Verbose mode.\n"; 847 print STDERR "\n"; 848 849 exit 0; 850} 851