]> git.sur5r.net Git - cc65/blob - src/ca65html/ca65html
Add several improvements, among others: Options, index page, link style...
[cc65] / src / ca65html / ca65html
1 #!/usr/bin/perl
2 ###############################################################################
3 #                                                                             #
4 #                                   main.c                                    #
5 #                                                                             #
6 #                      Convert a ca65 source into HTML                        #
7 #                                                                             #
8 #                                                                             #
9 #                                                                             #
10 #  (C) 2000      Ullrich von Bassewitz                                        #
11 #                Wacholderweg 14                                              #
12 #                D-70597 Stuttgart                                            #
13 #  EMail:        uz@musoftware.de                                             #
14 #                                                                             #
15 #                                                                             #
16 #  This software is provided 'as-is', without any expressed or implied        #
17 #  warranty.  In no event will the authors be held liable for any damages     #
18 #  arising from the use of this software.                                     #
19 #                                                                             #
20 #  Permission is granted to anyone to use this software for any purpose,      #
21 #  including commercial applications, and to alter it and redistribute it     #
22 #  freely, subject to the following restrictions:                             #
23 #                                                                             #
24 #  1. The origin of this software must not be misrepresented; you must not    #
25 #     claim that you wrote the original software. If you use this software    #
26 #     in a product, an acknowledgment in the product documentation would be   #
27 #     appreciated but is not required.                                        #
28 #  2. Altered source versions must be plainly marked as such, and must not    #
29 #     be misrepresented as being the original software.                       #
30 #  3. This notice may not be removed or altered from any source               #
31 #     distribution.                                                           #
32 #                                                                             #
33 ###############################################################################
34
35
36
37 use strict 'vars';
38 use warnings;
39
40 # Modules
41 use Getopt::Long;
42
43
44
45 #-----------------------------------------------------------------------------#
46 #                                  Variables                                  #
47 # ----------------------------------------------------------------------------#
48
49
50
51 # Global variables
52 my %Files       = ();           # List of all files.
53 my $FileCount   = 0;            # Number of input files
54 my %Exports     = ();           # List of exported symbols.
55 my %Imports     = ();           # List of imported symbols.
56 my %Labels      = ();           # List of all labels
57 my $LabelNum    = 0;            # Counter to generate unique labels
58
59 # Command line options
60 my $BGColor     = "#FFFFFF";    # Background color
61 my $Debug       = 0;            # No debugging
62 my $Help        = 0;            # Help flag
63 my $IndexCols   = 6;            # Columns in the file listing
64 my $IndexTitle  = "Index";      # Title of index page
65 my $IndexName   = "index.html"; # Name of index page
66 my $IndexPage   = 0;            # Create an index page
67 my $LinkStyle   = 0;            # Default link style
68 my $ReplaceExt  = 0;            # Replace extension instead of appending
69 my $TextColor   = "#000000";    # Text color
70 my $Verbose     = 0;            # Be quiet
71
72
73
74 #-----------------------------------------------------------------------------#
75 #                              Helper functions                               #
76 # ----------------------------------------------------------------------------#
77
78
79
80 # Terminate with an error
81 sub Abort {
82     print STDERR "ca65html: @_\n";
83     exit 1;
84 }
85
86 # Print a message if verbose is true
87 sub Gabble {
88     if ($Verbose) {
89         print "ca65html: @_\n";
90     }
91 }
92
93 # Generate a label and return it
94 sub GenLabel {
95     # Generate the label
96     return sprintf ("L%06X", $LabelNum++);
97 }
98
99 # Make an output file name from an input file name
100 sub GetOutName {
101
102     # Input name is parameter
103     my $InName = $_[0];
104
105     # Create the output file name from the input file name
106     if ($ReplaceExt && $InName =~ /^(.+)\.([^\.\/]*)$/) {
107         return "$1.html";
108     } else {
109         return "$InName.html";
110     }
111 }
112
113 # Remove illegal characters from a string
114 sub Cleanup {
115     my $S = shift (@_);
116     $S =~ s/&/&/g;
117     $S =~ s/</&lt;/g;
118     $S =~ s/>/&gt;/g;
119     $S =~ s/\"/&quot;/g;
120     return $S;
121 }
122
123
124
125 #-----------------------------------------------------------------------------#
126 #                         Document header and footer                          #
127 # ----------------------------------------------------------------------------#
128
129
130
131 # Print the document header
132 sub DocHeader {
133     my $OUT = shift (@_);
134     my $Asm = shift (@_);
135     print $OUT <<"EOF";
136 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html-40/loose.dtd">
137 <html>
138 <head>
139 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
140 <meta name="GENERATOR" content="ca65html">
141 <title>$Asm</title>
142 </head>
143 <body bgcolor="$BGColor" text="$TextColor" link="#0000d0" vlink="#000060" alink="#00d0d0">
144 <p><br><p>
145 <center><h1>$Asm</h1></center>
146 <hr><p><br><p>
147 <pre>
148 EOF
149 }
150
151 # Print the document footer
152 sub DocFooter {
153     my $OUT  = shift (@_);
154     my $Name = shift (@_);
155
156     # Get the current date and time
157     my $Today = localtime;
158
159     print $OUT <<"EOF";
160 </pre>
161 <p><br><p>
162 <hr size=1 noshade>
163 <address>
164     <a href=\"http://validator.w3.org/check/referer\"><img border=0
165        src=\"http://validator.w3.org/images/vh40\"
166        alt=\"Valid HTML 4.0!\" height=31 width=88 align=right></a>
167     $Name; generated on $Today by ca65html<br>
168     <a href=\"mailto:uz\@cc65.org\">uz\@cc65.org</a>
169 </address>
170 </body>
171 </html>
172 EOF
173 }
174
175
176
177 #-----------------------------------------------------------------------------#
178 #                            File list management                             #
179 # ----------------------------------------------------------------------------#
180
181
182
183 sub AddFile {
184
185     # Argument is file to add
186     my $FileName = $_[0];
187
188     # Remove a path name if we have one
189     $FileName =~ /^(.*?)([^\/]*)$/;
190     my $Path = $1;
191     my $Name = $2;
192
193     # Check if we have the file already
194     if (exists ($Files{$Name})) {
195         Gabble ("File \"$FileName\" already known");
196         return;
197     }
198
199     # Check with the full pathname. If we don't find it, search in the current
200     # directory
201     if (-f $FileName && -r $FileName) {
202         $Files{$Name} = $FileName;
203         $FileCount++;
204     } elsif (-f $Name && -r $Name) {
205         $Files{$Name} = $Name;
206         $FileCount++;
207     } else {
208         Abort ("$FileName not found or not readable");
209     }
210 }
211
212
213
214 #-----------------------------------------------------------------------------#
215 #                       Referencing and defining labels                       #
216 # ----------------------------------------------------------------------------#
217
218
219
220 # Get a label reference
221 sub RefLabel {
222
223     # Arguments are: Filename, identifier, item that should be tagged
224     my $FileName = $_[0];
225     my $Id       = $_[1];
226     my $Item     = $_[2];
227
228     # Search for the identifier in the list of labels
229     if (exists ($Labels{$FileName}{$Id})) {
230         # It is a label (in this file)
231         return sprintf ("<a href=\"#%s\">%s</a>", $Labels{$FileName}{$Id}, $Item);
232     } elsif (exists ($Imports{$FileName}{$Id})) {
233         # It is an import. If LinkStyle is 1, or if the file exporting the
234         # identifier is not visible, we link to the .import statement in the
235         # current file. Otherwise we link directly to the referenced symbol
236         # in the file that exports it.
237         if ($LinkStyle == 1 or not exists ($Exports{$Id})) {
238             return sprintf ("<a href=\"#%s\">%s</a>", $Imports{$FileName}{$Id}, $Item);
239         } else {
240             # Get the filename from the export
241             my $Label;
242             ($FileName, $Label) = split (/#/, $Exports{$Id});
243             if (not defined ($Labels{$FileName}{$Id})) {
244                 # This may currently happen because we don't see .include
245                 # statements, so we may have an export but no definition.
246                 # Link to the .export statement instead
247                 $Label = $Exports{$Id};
248             } else {
249                 # Link to the definition in the file
250                 $Label = sprintf ("%s#%s", $FileName, $Labels{$FileName}{$Id});
251             }
252             return sprintf ("<a href=\"%s\">%s</a>", $Label, $Item);
253         }
254     } else {
255         # The symbol is unknown, return as is
256         return $Item;
257     }
258 }
259
260
261
262 #-----------------------------------------------------------------------------#
263 #                                   Pass 1                                    #
264 # ----------------------------------------------------------------------------#
265
266
267
268 # Process1: Read one file for the first time.
269 sub Process1 {
270
271     # Variables
272     my $Line;
273     my $Id;
274
275     # Filename is parameter
276     my $InName = shift(@_);
277
278     # Create the output file name from the input file name
279     my $OutName = GetOutName ($InName);
280
281     # Current cheap local label prefix is empty
282     my $CheapPrefix = "";
283
284     # Open a the input file
285     my $FileName = $Files{$InName};     # Includes path if needed
286     open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!");
287
288     # Read and process all lines from the file
289     while ($Line = <INPUT>) {
290
291         # Remove the newline
292         chop ($Line);
293
294         # Check for a label
295         if ($Line =~ /^\s*(\@?)([_a-zA-Z][_\w]*)\s*(:|=)/) {
296
297             # Is this a local label?
298             if ($1 eq "\@") {
299                 # Use the prefix
300                 $Id = "$CheapPrefix$1$2";
301             } else {
302                 # Use as is
303                 $Id = $2;
304                 # Remember the id as new cheap local prefix
305                 $CheapPrefix = $Id;
306             }
307
308             # Remember the label
309             $Labels{$OutName}{$Id} = GenLabel();
310
311         # Check for an import statement
312         } elsif ($Line =~ /^\s*(\.import|\.importzp)\s+(.*?)(\s*)(;.*$|$)/) {
313
314             # Split into a list of identifiers
315             my @Ids = split (/\s*,\s*/, $2);
316             for $Id (@Ids) {
317                 $Imports{$OutName}{$Id} = GenLabel();
318             }
319
320         # Check for an export statement
321         } elsif ($Line =~ /^\s*(\.export|\.exportzp)\s+(.*?)(\s*)(;.*$|$)/) {
322
323             # Split into a list of identifiers
324             my @Ids = split (/\s*,\s*/, $2);
325             for $Id (@Ids) {
326                 $Exports{$Id} = sprintf ("%s#%s", $OutName, GenLabel());
327             }
328
329         # Check for a .proc statement
330         } elsif ($Line =~ /^\s*\.proc\s+([_a-zA-Z][_\w]*)?.*$/) {
331
332             # Do we have an id?
333             $Id = $1;
334             if ($Id ne "") {
335                 $Labels{$OutName}{$Id} = GenLabel();
336             }
337
338         }
339     }
340
341     # Close the input file
342     close (INPUT);
343 }
344
345
346
347 # Pass1: Read all files for the first time.
348 sub Pass1 () {
349
350     # Walk over the files
351     for my $InName (keys (%Files)) {
352
353         # Process one file
354         Process1 ($InName);
355
356     }
357 }
358
359
360
361 #-----------------------------------------------------------------------------#
362 #                                   Pass 2                                    #
363 # ----------------------------------------------------------------------------#
364
365
366
367 # Process2: Read one file the second time.
368 sub Process2 {
369
370     # Variables
371     my $Base;
372     my $Ext;
373     my $Line;
374     my $OutLine;
375     my $Id;
376     my $Label;
377     my $Operand;
378     my $Comment;
379
380     # Input file is parameter
381     my $InName = shift(@_);
382
383     # Create the output file name from the input file name
384     my $OutName = GetOutName ($InName);
385
386     # Current cheap local label prefix is empty
387     my $CheapPrefix = "";
388
389     # Open a the input file
390     my $FileName = $Files{$InName};     # Includes path if needed
391     open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!");
392
393     # Open the output file and print the HTML header
394     open (OUTPUT, ">$OutName") or Abort ("Cannot open $OutName: $!");
395     DocHeader (OUTPUT, $InName);
396
397     # The instructions that will have hyperlinks if a label is used
398     my $Ins = "adc|add|and|bcc|bcs|beq|bit|bmi|bne|bpl|bcv|bra|bvs|".
399               "cmp|cpx|cpy|dec|eor|inc|jmp|jsr|lda|ldx|ldy|ora|rol|".
400               "sbc|sta|stx|sty|sub|";
401
402     # Read the input file, replacing references by hyperlinks and mark
403     # labels as link targets.
404     while ($Line = <INPUT>) {
405
406         # Remove the newline
407         chop ($Line);
408
409         # Clear the output line
410         $OutLine = "";
411
412         # Check for a label. If we have one, process it and remove it
413         # from the line
414         if ($Line =~ /^\s*?(\@?)([_a-zA-Z][_\w]*)(\s*)(:|=)(.*)$/) {
415
416             # Is this a local label?
417             if ("$1" eq "\@") {
418                 # Use the prefix
419                 $Id = "$CheapPrefix$1$2";
420             } else {
421                 # Use as is
422                 $Id = $2;
423                 # Remember the id as new cheap local prefix
424                 $CheapPrefix = $Id;
425             }
426
427             # Get the label for the id
428             $Label = $Labels{$OutName}{$Id};
429
430             # Print the label with a tag
431             $OutLine .= sprintf ("<a name=\"%s\">%s%s</a>%s%s", $Label, $1, $2, $3, $4);
432
433             # Use the remainder for line
434             $Line = $5;
435         }
436
437         # Print any leading whitespace and remove it, so we don't have to
438         # care about whitespace below.
439         if ($Line =~ /^(\s+)(.*)$/) {
440             $OutLine .= "$1";
441             $Line = $2;
442         }
443
444         # Handle the import statements
445         if ($Line =~ /^(\.import|\.importzp)(\s+)(.*)$/) {
446
447             # Print any fixed stuff from the line and remove it
448             $OutLine .= "$1$2";
449             $Line = $3;
450
451             # Print all identifiers if there are any
452             while ($Line =~ /^([_a-zA-Z][_\w]*)(.*)$/) {
453
454                 # Identifier is $1, remainder is $2
455                 $Id = $1;
456                 $Line = $2;
457
458                 # Variable to assemble HTML representation
459                 my $Item = $Id;
460
461                 # If we have an export for this import, add a link to this
462                 # export definition
463                 if (exists ($Exports{$Id})) {
464                     $Label = $Exports{$Id};
465                     $Item = sprintf ("<a href=\"%s\">%s</a>", $Label, $Item);
466                 }
467
468                 # Make this import a link target
469                 if (exists ($Imports{$OutName}{$Id})) {
470                     $Label = $Imports{$OutName}{$1};
471                     $Item = sprintf ("<a name=\"%s\">%s</a>", $Label, $Item);
472                 }
473
474                 # Add the HTML stuff to the output line
475                 $OutLine .= $Item;
476
477                 # Check if another identifier follows
478                 if ($Line =~ /^(\s*),(\s*)(.*)$/) {
479                     $OutLine .= "$1,$2";
480                     $Line = $3;
481                 } else {
482                     last;
483                 }
484             }
485
486             # Add an remainder if there is one
487             $OutLine .= Cleanup ($Line);
488
489         # Handle export statements
490         } elsif ($Line =~ /^(\.export|\.exportzp)(\s+)(.*)$/) {
491
492             # Print the command the and white space
493             $OutLine .= "$1$2";
494             $Line = $3;
495
496             # Print all identifiers if there are any
497             while ($Line =~ /^([_a-zA-Z][_\w]*)(.*)$/) {
498
499                 # Identifier is $1, remainder is $2
500                 $Id = $1;
501                 $Line = $2;
502
503                 # Variable to assemble HTML representation
504                 my $Item = $Id;
505
506                 # If we have a definition for this export in this file, add
507                 # a link to the definition.
508                 if (exists ($Labels{$OutName}{$1})) {
509                     $Label = $Labels{$OutName}{$1};
510                     $Item = sprintf ("<a href=\"#%s\">%s</a>", $Label, $Item);
511                 }
512
513                 # If we have this identifier in the list of exports, add a
514                 # jump target for the export.
515                 if (exists ($Exports{$Id})) {
516                     $Label = $Exports{$Id};
517                     # Be sure to use only the label part
518                     $Label =~ s/^(.*#)(.*)$/$2/;
519                     $Item = sprintf ("<a name=\"%s\">%s</a>", $Label, $Item);
520                 }
521
522                 # Add the HTML stuff to the output line
523                 $OutLine .= $Item;
524
525                 # Check if another identifier follows
526                 if ($Line =~ /^(\s*),(\s*)(.*)$/) {
527                     $OutLine .= "$1,$2";
528                     $Line = $3;
529                 } else {
530                     last;
531                 }
532             }
533
534             # Add an remainder if there is one
535             $OutLine .= Cleanup ($Line);
536
537         # Check for .addr and .word
538         } elsif ($Line =~ /^(\.addr|\.word)(\s+)(.*)$/) {
539
540             # Print the command the and white space
541             $OutLine .= "$1$2";
542             $Line = $3;
543
544             # Print all identifiers if there are any
545             while ($Line =~ /^([_a-zA-Z][_\w]*)(.*)$/) {
546                 if (exists ($Labels{$OutName}{$1})) {
547                     $Label = $Labels{$OutName}{$1};
548                     $OutLine .= sprintf ("<a href=\"#%s\">%s</a>", $Label, $1);
549                 } else {
550                     $OutLine .= "$1";
551                 }
552                 $Line = $2;
553                 if ($Line =~ /^(\s*),(\s*)(.*)$/) {
554                     $OutLine .= "$1,$2";
555                     $Line = $3;
556                 } else {
557                     last;
558                 }
559             }
560
561             # Add an remainder if there is one
562             $OutLine .= Cleanup ($Line);
563
564         # Handle .proc
565         } elsif ($Line =~ /^(\.proc\s+)([_a-zA-Z][_\w]*)?(.*)$/) {
566
567             # Do we have an identifier?
568             if ($2 ne "") {
569                 # Get the label for the id
570                 $Label = $Labels{$OutName}{$2};
571
572                 # Print the label with a tag
573                 $OutLine .= sprintf ("%s<a name=\"%s\">%s</a>", $1, $Label, $2);
574
575                 # Use the remainder for line
576                 $Line = $3;
577             }
578
579             # Cleanup the remainder and add it
580             $OutLine .= Cleanup ($Line);
581
582         # Check for any legal instruction
583         } elsif ($Line =~ /^($Ins)(\s+)(.*?)(\s*)(;.*$|$)/) {
584
585             # Print the instruction and white space
586             $OutLine .= "$1$2";
587
588             # Remember the remaining parts
589             $Operand = $3;
590             $Comment = Cleanup ("$4$5");
591
592             # Check for the first identifier in the operand and replace it
593             # by a hyperlink
594             if ($Operand =~ /^([^_a-zA-Z]*?)(\@?)([_a-zA-Z][_\w]*)(.*)$/) {
595
596                 # Is this a local label?
597                 if ("$2" eq "\@") {
598                     # Use the prefix
599                     $Id = "$CheapPrefix$2$3";
600                 } else {
601                     # Use as is
602                     $Id = $3;
603                 }
604
605                 # Get the reference to this label if we find it
606                 $Operand = Cleanup($1) . RefLabel($OutName, $Id, $2 . $3) . Cleanup($4);
607             }
608
609             # Reassemble and print the line
610             $OutLine .= "$Operand$Comment";
611
612         } else {
613
614             # Nothing known - print the line
615             $OutLine .= Cleanup ($Line);
616
617         }
618
619         # Print the result
620         print OUTPUT "$OutLine\n";
621     }
622
623     # Print the HTML footer
624     DocFooter (OUTPUT, $OutName);
625
626     # Close the files
627     close (INPUT);
628     close (OUTPUT);
629 }
630
631
632
633 # Pass2: Read all files the second time.
634 sub Pass2 () {
635
636     # Walk over the files
637     for my $InName (keys (%Files)) {
638
639         # Process one file
640         Process2 ($InName);
641
642     }
643 }
644
645
646
647 #-----------------------------------------------------------------------------#
648 #                            Create an index page                             #
649 # ----------------------------------------------------------------------------#
650
651
652
653 # Print a list of all files
654 sub FileIndex {
655
656     # File is argument
657     my $INDEX = $_[0];
658
659     # Print the file list in a table
660     print $INDEX "<h2>Files</h2><p>\n";
661     print $INDEX "<table border=\"0\" width=\"100%\">\n";
662     my $Count = 0;
663     for my $File (sort (keys (%Files))) {
664
665         #
666         if (($Count % $IndexCols) == 0) {
667             print $INDEX "<tr>\n";
668         }
669         printf $INDEX "<td><a href=\"%s\">%s</a></td>\n", GetOutName ($File), $File;
670         if (($Count % $IndexCols) == $IndexCols-1) {
671             print $INDEX "</tr>\n";
672         }
673         $Count++;
674     }
675     if (($Count % $IndexCols) != 0) {
676         print $INDEX "</tr>\n";
677     }
678     print $INDEX "</table><p><br><p>\n";
679 }
680
681
682
683 # Print a list of all exports
684 sub ExportIndex {
685
686     # File is argument
687     my $INDEX = $_[0];
688
689     # Print the file list in a table
690     print $INDEX "<h2>Exports</h2><p>\n";
691     print $INDEX "<table border=\"0\" width=\"100%\">\n";
692     my $Count = 0;
693     for my $Export (sort (keys (%Exports))) {
694
695         # Get the export
696         my $File;
697         my $Label;
698         ($File, $Label) = split (/#/, $Exports{$Export});
699
700         # The label is the label of the export statement. If we can find the
701         # actual label, use this instead.
702         if (exists ($Labels{$File}{$Export})) {
703             $Label = $Labels{$File}{$Export};
704         }
705
706         #
707         if (($Count % $IndexCols) == 0) {
708             print $INDEX "<tr>\n";
709         }
710         printf $INDEX "<td><a href=\"%s#%s\">%s</a></td>\n", $File, $Label, $Export;
711         if (($Count % $IndexCols) == $IndexCols-1) {
712             print $INDEX "</tr>\n";
713         }
714         $Count++;
715     }
716     if (($Count % $IndexCols) != 0) {
717         print $INDEX "</tr>\n";
718     }
719     print $INDEX "</table><p><br><p>\n";
720 }
721
722
723
724 sub CreateIndex {
725
726     # Open the index page file
727     open (INDEX, ">$IndexName") or Abort ("Cannot open $IndexName: $!");
728
729     # Print the header
730     print INDEX <<"EOF";
731 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html-40/loose.dtd">
732 <html>
733 <head>
734 <meta http-equiv="Content-Type" content=\"text/html; charset=iso-8859-1">
735 <meta name="GENERATOR" content="ca65html">
736 <title>$IndexTitle</title>
737 </head>
738 <body bgcolor="$BGColor" text="$TextColor" link="#0000d0" vlink="#000060" alink="#00d0d0">
739 <p><br><p>
740 <center><h1>$IndexTitle</h1></center>
741 <hr><p><br><p>
742 EOF
743
744     # Print the file list in a table
745     FileIndex (INDEX);
746     ExportIndex (INDEX);
747
748     # Print the document footer
749     my $Today = localtime;
750     print INDEX <<"EOF";
751 <p><br><p>
752 <hr size=1 noshade>
753 <address>
754     <a href="http://validator.w3.org/check/referer"><img border=0
755        src="http://validator.w3.org/images/vh40"
756        alt="Valid HTML 4.0!" height="31" width="88" align=right></a>
757     $IndexName; generated on $Today by ca65html<br>
758     <a href=\"mailto:uz\@cc65.org\">uz\@cc65.org</a>
759 </address>
760 </body>
761 </html>
762 EOF
763
764     # Close the index file
765     close (INDEX);
766 }
767
768
769
770 #-----------------------------------------------------------------------------#
771 #                           Print usage information                           #
772 # ----------------------------------------------------------------------------#
773
774
775
776 sub Usage {
777     print "Usage: ca65html [options] file ...\n";
778     print "Options:\n";
779     print "\t--bgcolor c\tUse background color c instead of $BGColor\n";
780     print "\t--help\t\tThis text\n";
781     print "\t--indexcols n\tUse n columns on index page (default $IndexCols)\n";
782     print "\t--indexname f\tUse name f for the index file instead of $IndexName\n";
783     print "\t--indexpage\tCreate an index page\n";
784     print "\t--indextitle t\tUse t as the index title instead of $IndexTitle\n";
785     print "\t--linkstyle s\tUse the given link style\n";
786     print "\t--replaceext\tReplace source extension instead of appending .html\n";
787     print "\t--textcolor c\tUse text color c instead of $TextColor\n";
788     print "\t--verbose\tBe more verbose\n";
789 }
790
791
792
793 #-----------------------------------------------------------------------------#
794 #                                    Main                                     #
795 # ----------------------------------------------------------------------------#
796
797
798
799 # Get program options
800 GetOptions ("bgcolor=s"         => \$BGColor,
801             "debug!"            => \$Debug,
802             "help"              => \$Help,
803             "indexcols=i"       => \$IndexCols,
804             "indexname=s"       => \$IndexName,
805             "indexpage"         => \$IndexPage,
806             "indextitle=s"      => \$IndexTitle,
807             "linkstyle=i"       => \$LinkStyle,
808             "replaceext"        => \$ReplaceExt,
809             "textcolor=s"       => \$TextColor,
810             "verbose!"          => \$Verbose,
811             "<>"                => \&AddFile);
812
813 # Check some arguments
814 if ($IndexCols <= 0 || $IndexCols >= 20) {
815     Abort ("Invalid value for --indexcols option");
816 }
817
818 # Print help if requested
819 if ($Help) {
820     Usage ();
821 }
822
823 # Check if we have input files given
824 if ($FileCount == 0) {
825     Abort ("No input files");
826 }
827
828 # Convert the documents
829 Pass1 ();
830 Pass2 ();
831
832 # Generate an index page if requested
833 if ($IndexPage) {
834     CreateIndex ();
835 }
836
837 # Done
838 exit 0;
839