]> git.sur5r.net Git - cc65/blob - src/ca65html/ca65html
New tool
[cc65] / src / ca65html / ca65html
1 #!/usr/bin/perl
2
3 #
4 # Convert a ca65 source into HTML
5 #
6 # Ullrich von Bassewitz, 05.12.2000
7 #
8
9
10
11 # ----------------------------------------------------------
12 #                        Helper functions
13 # ----------------------------------------------------------
14
15
16
17 # Terminate with an error
18 sub Abort {
19     print "@_\n";
20     exit 1;
21 }
22
23 # Print the document header
24 sub DocHeader {
25     local $OUT = shift (@_);
26     local $Asm = shift (@_);
27     print $OUT <<"EOF";
28 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html-40/loose.dtd">
29 <html>
30 <head>
31 <title>SDSL Traffic</title>
32 </head>
33
34 <body bgcolor="#FFFFFF" text="#000000" link="#0000d0" vlink="#000060" alink="#00d0d0">
35 <p><br><p>
36 <center><h1>$Asm</h1></center>
37 <hr><p><br><p>
38 <pre>
39
40 EOF
41 }
42
43 # Print the document footer
44 sub DocFooter {
45     local $OUT  = shift (@_);
46     local $Name = shift (@_);
47
48     # Get the current date and time
49     $Today = localtime;
50
51     print $OUT <<"EOF";
52 </pre>
53 <p><br><p>
54 <hr size=1 noshade>
55 <address>
56     <a href=\"http://validator.w3.org/check/referer\"><img border=0
57        src=\"http://validator.w3.org/images/vh40\"
58        alt=\"Valid HTML 4.0!\" height=31 width=88 align=right></a>
59     $Name; generated on $Today by ca65html<br>
60     <a href=\"mailto:uz\@cc65.org\">uz\@cc65.org</a>
61 </address>
62
63 </body>
64 </html>
65 EOF
66 }
67
68
69
70 # Remove illegal characters from a string
71 sub Cleanup {
72     local $S = shift (@_);
73     $S =~ s/&/&amp;/g;
74     $S =~ s/</&lt;/g;
75     $S =~ s/>/&gt;/g;
76     $S =~ s/\"/&quot;/g;
77     return $S;
78 }
79
80
81
82 # ----------------------------------------------------------
83 #                               Code
84 # ----------------------------------------------------------
85
86 # Get the arguments
87 if ($#ARGV != 1) {
88     printf STDERR "Usage: %s asm-file output-file\n", $ARGV[0];
89     exit (1);
90 }
91 $ASM = shift (@ARGV);
92 $OUT = shift (@ARGV);
93
94 # Open a the input file
95 open (ASM, "<$ASM") or Abort ("Cannot open $ASM");
96
97 # Read all lines and remember labels
98 $LNum = 1;
99 %Label = ();
100 while ($Line = <ASM>) {
101
102     # Remove the newline
103     chop ($Line);
104
105     # Check for a label
106     if ($Line =~ /^\s*([_\w][_\w\d]*)\s*(:|=)/) {
107         $Label { $1 } = $LNum++;
108     } elsif ($Line =~ /^\s*(\.import|\.importzp|.proc)\s+(.*?)(\s*)(;.*$|$)/) {
109         @L = split (/\s*,\s*/, $2);
110         for my $Id (@L) {
111             $Label { $Id } = $LNum++;
112         }
113     }
114 }
115
116 # Reset the file pointer to the beginning
117 seek (ASM, 0, 0);
118
119 # Open the output file and print the HTML header
120 open (OUT, ">$OUT") or Abort ("Cannot open $OUT");
121 DocHeader (OUT, $ASM);
122
123 # The instructions that will have hyperlinks if a label is used
124 $Ins = "adc|add|and|bcc|bcs|beq|bit|bmi|bne|bpl|bcv|bvs|cmp|cpx|cpy|dec|".
125        "eor|inc|jmp|jsr|lda|ldx|ldy|ora|rol|sbc|sta|stx|sty|sub|";
126
127 # Read the input file again, replacing references by hyperlinks and mark
128 # labels as link targets.
129 while ($Line = <ASM>) {
130
131     # Remove the newline
132     chop ($Line);
133
134     # Clear the output line
135     $OutLine = "";
136
137     # Check for and ignore a local label
138     if ($Line =~ /^(\s*\@[_\w][_\w\d]*\s*:)(.*)$/) {
139         # Print the label
140         $OutLine .= "$1";
141         # Use the remainder for line
142         $Line = $2;
143     }
144
145     # Check for a label, if we have one, remove it from the line
146     if ($Line =~ /^\s*([_\w][_\w\d]*)(\s*)(:|=)(.*)$/) {
147         # Print the label with a tag
148         $OutLine .= sprintf ("<a name=\"L%04X\">%s</a>%s%s", $Label { $1 }, $1, $2, $3);
149         # Use the remainder for line
150         $Line = $4;
151     }
152
153     # Print any leading whitespace
154     if ($Line =~ /^(\s+)(.*)$/) {
155         $OutLine .= "$1";
156         $Line = $2;
157     }
158
159     # Handle the import statements
160     if ($Line =~ /^(\.import|\.importzp|.proc|)(\s+)(.*)$/) {
161         $OutLine .= "$1$2";
162         $Line = $3;
163
164         # Print all identifiers if there are any
165         while ($Line =~ /^([_\w][_\w\d]*)(.*)$/) {
166             $Num = $Label { $1 };
167             if ($Num != 0) {
168                 $OutLine .= sprintf ("<a name=\"L%04X\">%s</a>", $Num, $1);
169             } else {
170                 $OutLine .= "$1";
171             }
172             $Line = $2;
173             if ($Line =~ /^(\s*),(\s*)(.*)$/) {
174                 $OutLine .= "$1,$2";
175                 $Line = $3;
176             } else {
177                 last;
178             }
179         }
180
181         # Add an remainder if there is one
182         $OutLine .= Cleanup ($Line);
183
184     # Check for control commands that may reference lists of labels
185     } elsif ($Line =~ /^(\.addr|\.word|\.export)(\s+)(.*)$/) {
186
187         # Print the command the and white space
188         $OutLine .= "$1$2";
189         $Line = $3;
190
191         # Print all identifiers if there are any
192         while ($Line =~ /^([_\w][_\w\d]*)(.*)$/) {
193             $Num = $Label { $1 };
194             if ($Num != 0) {
195                 $OutLine .= sprintf ("<a href=\"#L%04X\">%s</a>", $Num, $1);
196             } else {
197                 $OutLine .= "$1";
198             }
199             $Line = $2;
200             if ($Line =~ /^(\s*),(\s*)(.*)$/) {
201                 $OutLine .= "$1,$2";
202                 $Line = $3;
203             } else {
204                 last;
205             }
206         }
207
208         # Add an remainder if there is one
209         $OutLine .= Cleanup ($Line);
210
211     # Check for any legal instruction
212     } elsif ($Line =~ /^($Ins)(\s+)(.*)$/) {
213
214         # Print the instruction and white space
215         $OutLine .= "$1$2";
216         $Line = $3;
217
218         # Check for a comment or traling whitespace and separate it
219         if ($Line =~ /^(.*?)(\s*)(;.*)$/) {
220             $Line    = $1;
221             $Comment = "$2$3";
222         } elsif ($Line =~ /^(.*?)(\s*)$/) {
223             $Line    = $1;
224             $Comment = $2;
225         } else {
226             $Comment = "";
227         }
228
229         # Check for the first identifier and replace it by a hyperlink
230         if ($Line =~ /^([^_a-zA-Z]*)([_a-zA-Z][_\w]*)(.*)$/ && $Label { $2 } != 0) {
231             $Line = sprintf ("%s<a href=\"#L%04X\">%s</a>%s",
232                     Cleanup ($1), $Label { $2 }, $2, Cleanup ($3));
233         }
234
235         # Clean the comment
236         $Comment = Cleanup ($Comment);
237
238         # Reassemble and print the line
239         $OutLine .= "$Line$Comment";
240
241     } else {
242
243         # Nothing known - print the line
244         $OutLine .= Cleanup ($Line);
245
246     }
247
248     # Print the result
249     print OUT "$OutLine\n";
250 }
251
252 # Print the HTML footer
253 DocFooter (OUT, $OUT);
254
255 # Close the files
256 close (ASM);
257 close (OUT);
258
259 # Done
260 exit 0;
261