blob: d065c6df60d18d8d590d74810d3af0b1498e70b5 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001#!/usr/bin/perl -w
2#
3# Format ImageMagick comments into POD-format or HTML format
4# documentation
5# Produces *.pod or *.html files corresponding to *.c files
6#
7# Written by Bob Friesenhahn, April 1997
8#
9
10$opt_format='html';
11$opt_srcdir='';
12$opt_outdir='';
13
14use Getopt::Long;
15if ( ! GetOptions(
16 'format=s' => \$opt_format,
17 'srcdir=s' => \$opt_srcdir,
18 'outdir=s' => \$opt_outdir,
19 )
20 ) {
21 print("Usage: fmtdocs [-srcdir srcdir] [-outdir outdir] [-format format] \n");
22 exit(1);
23}
24
25#
26# Source files to use
27#
28@srcs = ('animate.c',
29 'annotate.c',
30 'attribute.c',
31 'blob.c',
32 'cache.c',
33 'cache-view.c',
34 'color.c',
35 'colorspace.c',
36 'compare.c',
37 'composite.c',
38 'constitute.c',
39 'decorate.c',
40 'deprecate.c',
41 'draw.c',
42 'drawing-wand.c',
43 'display.c',
44 'effect.c',
45 'enhance.c',
46 'exception.c',
47 'fx.c',
48 'image.c',
49 'list.c',
50 'magick.c',
51 'magick-wand.c',
52 'memory.c',
53 'monitor.c',
54 'montage.c',
55 'paint.c',
56 'pixel-iterator.c',
57 'pixel-wand.c',
58 'profile.c',
59 'quantize.c',
60 'registry.c',
61 'resource.c',
62 'segment.c',
63 'shear.c',
64 'signature.c',
65 'stream.c',
66 'transform.c',
67 'resize.c',
68 'version.c');
69
70$tmpname_pre_format = "/tmp/fmtdocs_pre.$$";
71$tmpname_pod = "/tmp/fmtdocs_pod.$$";
72$tmpname_html = "/tmp/fmtdocs_html.$$";
73
74#@srcs = ('draw.c');
75
76#
77# What is for source files
78#
79%whatis =
80(
81 'animate', 'Interactively Animate an Image Sequence',
82 'annotate', 'Annotate an Image',
83 'attribute', 'Set Text Attributes',
84 'blob', 'Read or Write Binary Large OBjects',
85 'color', 'Count the Colors in an Image',
86 'colorspace', 'Dealing with Image Colorspaces',
87 'compare', 'Compare an Image to a Reconstructed Image',
88 'constitute', 'Constitute an Image',
89 'composite', 'Composite an Image',
90 'decorate', 'Decorate an Image',
91 'deprecate', 'Deprecated Methods',
92 'display', 'Interactively Display and Edit an Image',
93 'draw', 'Draw on an Image',
94 'drawing_wand', 'Image Vector Drawing',
95 'effect', 'Add an Effect',
96 'fx', 'Add a Special Effect',
97 'enhance', 'Enhance an Image',
98 'exception', 'Dealing with Exceptions',
99 'image', 'Image Methods',
100 'list', 'Working with Image Lists',
101 'cache', 'Get or Set Image Pixels',
102 'cache_view', 'Working with Cache Views',
103 'magick', 'Read or List Image formats',
104 'magick_wand', 'Magick Wand',
105 'memory', 'Memory Allocation',
106 'monitor', 'Monitor the Progress of an Image Operation',
107 'montage', 'Create an Image Thumbnail',
108 'paint', 'Paint on an Image',
109 'pixel_iterator', 'Pixel Iterator',
110 'pixel_wand', 'Pixel Wand',
111 'profile', 'Dealing with Image Profiles',
112 'quantize', 'Reduce the Number of Unique Colors in an Image',
113 'registry', 'The Registry',
114 'resource', 'Minitor or Limit Resource Consumption',
115 'segment', 'Segment an Image with Thresholding Fuzzy c-Means',
116 'shear', 'Shear or Rotate an Image by an Arbitrary Angle',
117 'signature', 'Compute a Digital Signature for an Image',
118 'stream', 'The Pixel FIFO',
119 'transform', 'Transform an Image',
120 'resize', 'Resize an Image',
121 'version', 'Get Version and Copyright',
122);
123
124#
125# Key words to replace with HTML links
126#
127my %keywords =
128 (
129 AffineMatrix => 'types.html#AffineMatrix',
130 BlobInfo => 'types.html#BlobInfo',
131 Cache => 'types.html#Cache',
132 ChannelType => 'types.html#ChannelType',
133 ChromaticityInfo => 'types.html#ChromaticityInfo',
134 ClassType => 'types.html#ClassType',
135 ClipPathUnits => 'types.html#ClipPathUnits',
136 ColorPacket => 'types.html#ColorPacket',
137 ColorspaceType => 'types.html#ColorspaceType',
138 ComplianceType => 'types.html#ComplianceType',
139 CompositeOperator => 'types.html#CompositeOperator',
140 CompressionType => 'types.html#CompressionType',
141 DecorationType => 'types.html#DecorationType',
142 DrawContext => 'types.html#DrawContext',
143 DrawInfo => 'types.html#DrawInfo',
144 ErrorHandler => 'types.html#ErrorHandler',
145 ExceptionInfo => 'types.html#ExceptionInfo',
146 ExceptionType => 'types.html#ExceptionType',
147 FillRule => 'types.html#FillRule',
148 FilterTypes => 'types.html#FilterTypes',
149 FrameInfo => 'types.html#FrameInfo',
150 GravityType => 'types.html#GravityType',
151 Image => 'types.html#Image',
152 ImageInfo => 'types.html#ImageInfo',
153 ImageType => 'types.html#ImageType',
154 InterlaceType => 'types.html#InterlaceType',
155 LayerType => 'types.html#LayerType',
156 MagickInfo => 'types.html#MagickInfo',
157 MonitorHandler => 'types.html#MonitorHandler',
158 MontageInfo => 'types.html#MontageInfo',
159 NoiseType => 'types.html#NoiseType',
160 PaintMethod => 'types.html#PaintMethod',
161 PixelPacket => 'types.html#PixelPacket',
162 PointInfo => 'types.html#PointInfo',
163 ProfileInfo => 'types.html#ProfileInfo',
164 QuantizeInfo => 'types.html#QuantizeInfo',
165 Quantum => 'types.html#Quantum',
166 QuantumType => 'types.html#QuantumType',
167 RectangleInfo => 'types.html#RectangleInfo',
168 RegistryType => 'types.html#RegistryType',
169 RenderingIntent => 'types.html#RenderingIntent',
170 ResolutionType => 'types.html#ResolutionType',
171 ResourceType => 'types.html#ResourceType',
172 SegmentInfo => 'types.html#SegmentInfo',
173 SignatureInfo => 'types.html#SignatureInfo',
174 StorageType => 'types.html#StorageType',
175 StreamHandler => 'types.html#StreamHandler',
176 StretchType => 'types.html#StretchType',
177 StyleType => 'types.html#StyleType',
178 TypeMetric => 'types.html#TypeMetric',
179 CacheView => 'types.html#CacheView',
180 VirtualPixelMethod => 'types.html#VirtualPixelMethod',
181 XResourceInfo => 'types.html#XResourceInfo',
182);
183
184
185foreach $src (@srcs) {
186
187 my($out,$command);
188
189 # Compute POD name
190 ($base = $src) =~ s/\.[^\.]*$//g;
191
192 $out = "${base}.${opt_format}";
193 if ("${opt_outdir}" ne "") {
194 $out = "${opt_outdir}/${base}.${opt_format}";
195 }
196
197 if ("${opt_srcdir}" ne "") {
198 $src = "${opt_srcdir}/${src}";
199 }
200
201 $command='pod2html -netscape';
202 if ( $opt_format eq 'html' ) {
203 $command='pod2html -netscape';
204 } elsif ( $opt_format eq 'latex' ) {
205 $command='pod2latex';
206 } elsif ( $opt_format eq 'man' ) {
207 $command='pod2man';
208 } elsif ( $opt_format eq 'text' ) {
209 $command='pod2text';
210 } elsif ( $opt_format eq 'pod' ) {
211 $command='cat';
212 }
213
214 print( "Processing $src -> $out\n" );
215
216 pre_format($src, $tmpname_pre_format); # Make easily parsed
217 format_to_pod($tmpname_pre_format, $tmpname_pod); # Format to pod.
218
219 if ( $opt_format eq 'html' ) {
220 system("$command $tmpname_pod > \"$tmpname_html\"");
221 reformat_html($tmpname_html,$out);
222 } else {
223 system("$command $tmpname_pod > \"$out\"");
224 }
225 unlink($tmpname_pre_format);
226 unlink($tmpname_pod);
227 unlink($tmpname_html);
228}
229
230#unlink($tmpname_pre_format);
231exit(0);
232
233#
234# Reformat pod2html-generated HTML into nicer form.
235#
236sub reformat_html {
237 my($infile, $outfile) = @_;
238
239 open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
240 open( OUT, ">$outfile" ) || die("Failed to open \"$outfile\" for write\n" );
241
242 INPUT:
243 while(<IN>) {
244 s|<\!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">|<\!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
245 "http://www.w3.org/TR/html4/loose.dtd">|;
246 s|<HEAD>|<HEAD>
247<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
248<STYLE>
249<!--
250\@page { size: 8.5in 11in }
251TD P { color: #000000; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 12pt }
252P { color: #000000; font-family: "Verdana", "Arial", "Helvetica", sans-serif; font-size: 12pt }
253H2 { color: #000000 }
254A:link { color: #0085c0 }
255A:visited { color: #800080 }
256-->
257</STYLE>
258|;
259 s|<link rev="made" href="mailto:root\@localhost" />|<link rel="stylesheet" type="text/css" href="../magick.css">|;
260 s|<body style="background-color: white">|<body marginheight="1" marginwidth="1" topmargin="1" leftmargin="1">
261<a name="top"></a>
262<table border="0" cellpadding="0" cellspacing="0" summary="Masthead" width="100%">
263<tbody>
264<tr>
265<td bgcolor="#003399" width="25%" height="118" background="../../images/background.gif"><a href="http://www.imagemagick.org/"><img src="../../images/script.gif" width="278" height="118" border="0" alt="" /></a></td>
266<td bgcolor="#003399" width="60%" height="118" background="../../images/background.gif"><a href="http://www.networkeleven.com/direct.php?magick_all"><img src="../../images/promote.png" border="0" width="186" height="52" vspace="29" alt="Powered by NetworkEleven" /></a></td>
267<td bgcolor="#003399" width="114" height="118" align="right"><img src="../../images/sprite.png" width="114" height="118" alt="" /></td>
268<td bgcolor="#003399" width="114" height="118" align="right"><a href="http://www.imagemagick.net"><img src="../../images/logo.png" width="114" height="118" border="0" alt="ImageMagick logo" /></a></td>
269</tr></tbody></table>
270<table align="left" border="0" cellpadding="2" cellspacing="2" summary="Navigation buttons" width="20%">
271<tr>
272<td>
273<form target="_self" action="../../index.html"><input type="submit" title="ImageMagick Home" value=" Home" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td>
274<td>
275<form target="_self" action="../../www/apis.html"><input type="submit" title="ImageMagick API" value=" API " style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td>
276<td>
277<form target="_self" action="../../www/download.html"><input type="submit" title="ImageMagick Download" value="Download" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold"></form></td></tr></table>
278<div align="right" style="margin-top:3px; padding-right:4px">
279<form action="http://studio.imagemagick.org/Sage/scripts/Sage.cgi"><input type="TEXT" name="query" size="32" maxlength="255"> <input type="SUBMIT" name="sa" value="Search" style="background-color: #1947A3; background-image:url('../../../images/background.gif'); bgcolor:#003399; color:#fbc713; font-weight:bold"></form></div>
280<table align="left" border="0" cellpadding="10" cellspacing="0" style="margin-top:-17px" width="100%">
281<tr>
282<td>
283|;
284 s|</body>|
285<HR>
286
287<a href="#top"><img src="../../../images/top.gif" border=0 width="35" height="46" align="right" alt="Top of page"></a>
288<form action="http://studio.imagemagick.org/magick/" style="margin-top:5px">
289<input type="submit" title="Help!" value="Help!" style="background-image:url('../../../images/background.gif'); color:#fbc713; font-weight:bold">
290 <small>&quot;Image manipulation software that works like magick&quot;</small>
291</form></td>
292</tr></table>
293
294</body>
295|;
296 s|<FONT SIZE=-1>||g;
297 s|</FONT>||g;
298
299 s|<H2>|<H3>|g;
300 s|</H2>|</H3>|g;
301
302 s|<H1>|<H2>|g;
303 s|</H1>|</H2>|g;
304
305 s|<DT>|<DD><P></P><DT>|g;
306 s|<DL>|<DL><DT><DD><DL>|g;
307 s|</DL>|</DL></DL>|g;
308 s|<dd>|<DD>|g;
309 s|<p>|<P>|g;
310 s|</p>|</P>|g;
311 s|</LI>||g;
312 s|>o |>|g;
313 s|unsignedint|unsigned int|g;
314 print( OUT $_ );
315 }
316 close( TMP );
317 close( IN );
318}
319
320#
321# Pre-process file into intermediate form
322#
323# Initializes globals:
324#
325# @functions - Function names
326# %synopsis - Function synopsis
327#
328sub pre_format {
329 my($infile, $tmpfile) = @_;
330
331 my $inpara = 0; # Set to 1 if in paragraph
332 my $inlist = 0; # Set to 1 if in list-item paragraph
333
334 # Open C source file
335 open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
336
337 # Open TMP file
338 open( TMP, ">$tmpfile" ) || die("Failed to open \"$tmpfile\" for write\n" );
339
340 undef @functions;
341 undef %synopsis;
342
343 # Skip past first form feed
344 while(<IN>) {
345 last if m/\014/;
346 }
347
348LINE:
349 while(<IN>) {
350 if (m/^\+/) {
351 while(<IN>) {
352 last unless m/^%/;
353 }
354 next;
355 }
356 next unless m/^%/ ;
357 chop;
358
359 # Extract and save function title
360 if (m/^%\s+((\w )+)\s+%/) {
361 ($ftitle = $1) =~ s/ //g;
362 push(@functions, $ftitle);
363 print( TMP "===$ftitle\n" );
364 next;
365 }
366
367 # Zap text we don't want
368 next if ( m/^%.+%/ ); # "%*%
369 s/^%\s{0,2}//;
370
371 # Extract and save synopsis info
372 if (m /\(\)/ ) {
373 # nothing
374 ;
375 }
376 elsif ( m/${ftitle}\(.*\)$/ ) {
377 s/,/ , /g;
378 s/\(/ ( /g;
379 s/\)/ ) /g;
380 s/\*/ * /g;
381 s/\s+/ /g;
382
383 s/\(\s+\*/(*/g;
384 s/ ,/,/g;
385 s/ \(/(/g;
386 s/\) /)/g;
387 s/ \* / */g;
388
389 s/^\s*//;
390 $synopsis{$ftitle} = $_ . ';'; # Append semi-colon, prototype style
391 print ( TMP " " . $synopsis{$ftitle} . "\n" );
392 next LINE;
393 }
394 elsif ( m/${ftitle}\(.*/ ) {
395 $synopsis{$ftitle} = $_;
396 do {
397 $_ = <IN>;
398 chop;
399 # Zap text we don't want
400 next if m/^%.+%/; # "%*%
401 s/^%\s{0,2}//;
402 $synopsis{$ftitle} .= $_;
403 } until m/^\s*$/;
404 $_ = $synopsis{$ftitle};
405
406 s/,/ , /g;
407 s/\(/ ( /g;
408 s/\)/ ) /g;
409 s/\*/ * /g;
410 s/\s+/ /g;
411
412 s/\(\s+\*/(*/g;
413 s/ ,/,/g;
414 s/ \(/(/g;
415 s/\) /)/g;
416 s/ \* / */g;
417
418 s/^\s*//;
419 $synopsis{$ftitle} = $_ . ';'; # Append semi-colon, prototype style
420 print ( TMP " " . $synopsis{$ftitle} . "\n" );
421 next LINE;
422 }
423
424 # Keep track of paragraphing
425 if( ! m/^$/ ) {
426 if ( $inpara == 0 ) {
427 $inpara = 1; # Start of paragraph
428 $para = "$_"; # Start paragraph string
429 } else {
430 # Inside paragraph
431 $para .= " $_"; # Add line to paragraph
432 }
433 }
434 # Keep track of list items so they can
435 # be wrapped as a paragraph
436 if( m/^\s+(o[^:]+:|o|[0-9]\.)\s(.*)/ ) {
437 $inlist = 1;
438 }
439
440 if ( $inpara == 1 ) {
441 if( $para =~ m/^\s+\S+/ && ! $inlist ) {
442 # Lines that start with a space shouldn't be munged
443 $inpara = 0; # End of paragraph
444 $inlist = 0;
445 $para .= ""; # Terminate paragraph
446 print( TMP "$para\n" );
447 }
448 elsif( m/^$/ ) {
449 # End of paragraph
450 $inpara = 0; # End of paragraph
451 $inlist = 0;
452 $para .= ""; # Terminate paragraph
453 $para =~ s/^\s+//g; # Eliminate any leading space
454 $para =~ s/\s+/ /g; # Canonicalize whitespace
455 $para =~ s/ $//; # Trim final space
456 $para =~ s/([a-zA-Z0-9][.!?][)'"]*) /$1 /g; #' Fix sentance ends
457 print( TMP "\n$para\n\n" );
458 }
459 }
460 }
461
462 close( TMP );
463 close( IN );
464}
465
466#
467# Second pass
468# Process into formatted form
469#
470sub format_to_pod {
471 my($infile, $outfile) = @_;
472
473 my $func;
474
475 my $inlist = 0; # Set to one if in indented list
476
477 # Open input file
478 open( IN, "<$infile" ) || die("Failed to open \"$infile\" for read\n" );
479
480 # Open output file
481 open( OUT, ">$outfile" ) || die("Failed to open \"$outfile\" for write\n" );
482
483 # Name field
484 print( OUT head1("NAME") );
485 if (!defined($whatis{$base})) {
486 print("Whatis definition missing for \"$base\"!\n");
487 print( OUT "${base} - Unknown\n\n" );
488 } else {
489 print( OUT "${base} - $whatis{$base}\n\n" );
490 }
491
492 # Synopsis field (function signatures)
493 print( OUT head1("SYNOPSIS") );
494 foreach $func (sort( @functions )) {
495 if (defined $synopsis{$func} ) {
496 $_ = $synopsis{$func};
497 s/$func/ B<$func>/;
498 s/^\s*//;
499 my $synopsis = $_;
500 print( OUT $synopsis, "\n\n" );
501 }
502 }
503
504 # Description field
505 print( OUT head1("FUNCTION DESCRIPTIONS") );
506
507 while(<IN>){
508 chop;
509 next if m/^$/;
510
511 # Match list element
512 if( m/^(o[^:]+:|o|[0-9]\.?)\s(.*)/ ) {
513 my $bullet = $1;
514 my $bullet_text = $2;
515
516 print( OUT startlist() ) unless $inlist;
517 $inlist = 1;
518 print( OUT item($bullet), "$bullet_text\n\n" );
519 next;
520 } else {
521 print( OUT endlist() ) if $inlist;
522 $inlist = 0;
523 }
524
525 # Match synopsis item
526 if( defined $func && m/$func\s*\(.*\)/ ) {
527 # Split all words with spaces to aid with tokenization
528 s/,/ , /g;
529 s/\(/ ( /g;
530 s/\)/ ) /g;
531 s/\*/ * /g;
532
533 my $html = '';
534
535 # Replace tokens matching keywords with HTML links.
536TOKEN: foreach $token ( split(' ', $_ ) ) {
537 foreach $keyword ( %keywords ) {
538 if ( $token eq $keyword ) {
539 $html .= linked( $keyword, $keywords{$keyword} );
540 $html .= " ";
541 next TOKEN;
542 }
543 }
544 $html .= "$token ";
545 }
546 $_ = $html;
547 # Remove excess spaces
548 s/\s+/ /g;
549 s/ ,/,/g;
550 s/\* /*/g;
551 s/\)\s*\;/);/;
552 s/^\s*//;
553 s/ \( *\)/\(\)/;
554
555 # This is very poor because text is output specifically
556 # for HTML so the text isn't output at all for other target
557 # formats.
558 print( OUT html("<blockquote>$_</blockquote>") );
559 next;
560 }
561
562 # Match function title
563 if( m/===([a-zA-Z0-9]+)/ ) {
564 $func = $1;
565 print( OUT head2($func) );
566 next;
567 }
568
569 print( OUT "\n") if /^[^ ]/;
570 print( OUT "$_\n") ;
571 print( OUT "\n") if /^[^ ]/;
572 }
573
574 close( OUT );
575 close( IN );
576}
577
578#
579# Return level 1 heading
580# Similar to: <H1>heading</H1>
581#
582sub head1 {
583 my($heading) = @_;
584 return( "=head1 $heading\n\n" );
585}
586
587#
588# Return level 2 heading
589# Similar to: <H2>heading</H2>
590#
591sub head2 {
592 my($heading) = @_;
593 return( "=head2 $heading\n\n" );
594}
595
596
597#
598# Return item
599# Simlar to: <I>
600#
601sub item {
602 my($item) = @_;
603 return( "=item $item\n\n" );
604}
605
606
607#
608# Start list
609# Similar to: <UL>
610#
611sub startlist {
612 return( "=over 4\n\n" )
613}
614
615#
616# End list
617# Similar to: </UL>
618#
619sub endlist {
620 return( "=back\n\n" );
621}
622
623#
624# Preformatted text
625# Similar to <PRE></PRE>
626#
627sub formated {
628 my($text) = @_;
629 return( " $text\n\n" );
630}
631
632#
633# Raw HTML paragraph
634#
635sub html {
636 my($html) = @_;
637 return return( "=for html $html\n\n" );
638}
639
640#
641# HTML Link
642# Similar to: <A HREF="url">description</A>
643#
644sub linked {
645 local($description, $url) = @_;
646 return( "<A HREF=\"" . $url . "\">" . $description . "</A>" );
647}