~exarkun/pyopenssl/trunk

« back to all changes in this revision

Viewing changes to doc/tools/perl/python.perl

  • Committer: Jean-Paul Calderone
  • Date: 2011-09-11 19:49:43 UTC
  • mfrom: (156.3.22 sphinx-doc)
  • Revision ID: exarkun@divmod.com-20110911194943-ucaan2tzidk7ek5l
Convert the documentation from LaTeX/epytext to Sphinx/ReST

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# python.perl by Fred L. Drake, Jr. <fdrake@acm.org>            -*- perl -*-
2
 
#
3
 
# Heavily based on Guido van Rossum's myformat.perl (now obsolete).
4
 
#
5
 
# Extension to LaTeX2HTML for documents using myformat.sty.
6
 
# Subroutines of the form do_cmd_<name> here define translations
7
 
# for LaTeX commands \<name> defined in the corresponding .sty file.
8
 
 
9
 
package main;
10
 
 
11
 
use File::Basename;
12
 
 
13
 
 
14
 
sub next_argument{
15
 
    my $param;
16
 
    $param = missing_braces()
17
 
      unless ((s/$next_pair_pr_rx/$param=$2;''/eo)
18
 
              ||(s/$next_pair_rx/$param=$2;''/eo));
19
 
    return $param;
20
 
}
21
 
 
22
 
sub next_optional_argument{
23
 
    my($param,$rx) = ('', "^\\s*(\\[([^]]*)\\])?");
24
 
    s/$rx/$param=$2;''/eo;
25
 
    return $param;
26
 
}
27
 
 
28
 
sub make_icon_filename($){
29
 
    my($myname, $mydir, $myext) = fileparse(@_[0], '\..*');
30
 
    chop $mydir;
31
 
    if ($mydir eq '.') {
32
 
        $mydir = $ICONSERVER;
33
 
    }
34
 
    $myext = ".$IMAGE_TYPE"
35
 
      unless $myext;
36
 
    return "$mydir$dd$myname$myext";
37
 
}
38
 
 
39
 
sub get_link_icon($){
40
 
    my $url = @_[0];
41
 
    if ($OFF_SITE_LINK_ICON && ($url =~ /^[-a-zA-Z0-9.]+:/)) {
42
 
        # absolute URL; assume it points off-site
43
 
        my $icon = make_icon_filename($OFF_SITE_LINK_ICON);
44
 
        return (" <img src='$icon'\n"
45
 
                . "  border='0' class='offsitelink'"
46
 
                . ($OFF_SITE_LINK_ICON_HEIGHT
47
 
                   ? " height='$OFF_SITE_LINK_ICON_HEIGHT'"
48
 
                   : '')
49
 
                . ($OFF_SITE_LINK_ICON_WIDTH
50
 
                   ? " width='$OFF_SITE_LINK_ICON_WIDTH'"
51
 
                   : '')
52
 
                . " alt='[off-site link]'\n"
53
 
                . "  >");
54
 
    }
55
 
    return '';
56
 
}
57
 
 
58
 
# This is a fairly simple hack; it supports \let when it is used to create
59
 
# (or redefine) a macro to exactly be some other macro: \let\newname=\oldname.
60
 
# Many possible uses of \let aren't supported or aren't supported correctly.
61
 
#
62
 
sub do_cmd_let{
63
 
    local($_) = @_;
64
 
    my $matched = 0;
65
 
    s/[\\]([a-zA-Z]+)\s*(=\s*)?[\\]([a-zA-Z]*)/$matched=1; ''/e;
66
 
    if ($matched) {
67
 
        my($new, $old) = ($1, $3);
68
 
        eval "sub do_cmd_$new { do_cmd_$old" . '(@_); }';
69
 
        print "\ndefining handler for \\$new using \\$old\n";
70
 
    }
71
 
    else {
72
 
        s/[\\]([a-zA-Z]+)\s*(=\s*)?([^\\])/$matched=1; ''/es;
73
 
        if ($matched) {
74
 
            my($new, $char) = ($1, $3);
75
 
            eval "sub do_cmd_$new { \"\\$char\" . \@_[0]; }";
76
 
            print "\ndefining handler for \\$new to insert '$char'\n";
77
 
        }
78
 
        else {
79
 
            write_warnings("Could not interpret \\let construct...");
80
 
        }
81
 
    }
82
 
    return $_;
83
 
}
84
 
 
85
 
 
86
 
# the older version of LaTeX2HTML we use doesn't support this, but we use it:
87
 
 
88
 
sub do_cmd_textasciitilde{ '~' . @_[0]; }
89
 
 
90
 
 
91
 
# words typeset in a special way (not in HTML though)
92
 
 
93
 
sub do_cmd_ABC{ 'ABC' . @_[0]; }
94
 
sub do_cmd_UNIX{ 'Unix'. @_[0]; }
95
 
sub do_cmd_ASCII{ 'ASCII' . @_[0]; }
96
 
sub do_cmd_POSIX{ 'POSIX' . @_[0]; }
97
 
sub do_cmd_C{ 'C' . @_[0]; }
98
 
sub do_cmd_Cpp{ 'C++' . @_[0]; }
99
 
sub do_cmd_EOF{ 'EOF' . @_[0]; }
100
 
sub do_cmd_NULL{ '<tt class="constant">NULL</tt>' . @_[0]; }
101
 
 
102
 
sub do_cmd_e{ '&#92;' . @_[0]; }
103
 
 
104
 
$DEVELOPER_ADDRESS = '';
105
 
$SHORT_VERSION = '';
106
 
$PACKAGE_VERSION = '';
107
 
 
108
 
sub do_cmd_version{ $PACKAGE_VERSION . @_[0]; }
109
 
sub do_cmd_shortversion{ $SHORT_VERSION . @_[0]; }
110
 
sub do_cmd_release{
111
 
    local($_) = @_;
112
 
    $PACKAGE_VERSION = next_argument();
113
 
    return $_;
114
 
}
115
 
 
116
 
sub do_cmd_setshortversion{
117
 
    local($_) = @_;
118
 
    $SHORT_VERSION = next_argument();
119
 
    return $_;
120
 
}
121
 
 
122
 
sub do_cmd_authoraddress{
123
 
    local($_) = @_;
124
 
    $DEVELOPER_ADDRESS = next_argument();
125
 
    return $_;
126
 
}
127
 
 
128
 
#sub do_cmd_developer{ do_cmd_author(@_[0]); }
129
 
#sub do_cmd_developers{ do_cmd_author(@_[0]); }
130
 
#sub do_cmd_developersaddress{ do_cmd_authoraddress(@_[0]); }
131
 
 
132
 
sub do_cmd_hackscore{
133
 
    local($_) = @_;
134
 
    next_argument();
135
 
    return '_' . $_;
136
 
}
137
 
 
138
 
sub use_wrappers{
139
 
    local($_,$before,$after) = @_;
140
 
    my $stuff = next_argument();
141
 
    return $before . $stuff . $after . $_;
142
 
}
143
 
 
144
 
$IN_DESC_HANDLER = 0;
145
 
sub do_cmd_optional{
146
 
    if ($IN_DESC_HANDLER) {
147
 
        return use_wrappers(@_[0], "</var><big>\[</big><var>",
148
 
                            "</var><big>\]</big><var>");
149
 
    }
150
 
    else {
151
 
        return use_wrappers(@_[0], "<big>\[</big>", "<big>\]</big>");
152
 
    }
153
 
}
154
 
 
155
 
# Logical formatting (some based on texinfo), needs to be converted to
156
 
# minimalist HTML.  The "minimalist" is primarily to reduce the size of
157
 
# output files for users that read them over the network rather than
158
 
# from local repositories.
159
 
 
160
 
# \file and \samp are at the end of this file since they screw up fontlock.
161
 
 
162
 
sub do_cmd_pytype{ return @_[0]; }
163
 
sub do_cmd_makevar{
164
 
    return use_wrappers(@_[0], '<span class="makevar">', '</span>'); }
165
 
sub do_cmd_code{
166
 
    return use_wrappers(@_[0], '<code>', '</code>'); }
167
 
sub do_cmd_module{
168
 
    return use_wrappers(@_[0], '<tt class="module">', '</tt>'); }
169
 
sub do_cmd_keyword{
170
 
    return use_wrappers(@_[0], '<tt class="keyword">', '</tt>'); }
171
 
sub do_cmd_exception{
172
 
    return use_wrappers(@_[0], '<tt class="exception">', '</tt>'); }
173
 
sub do_cmd_class{
174
 
    return use_wrappers(@_[0], '<tt class="class">', '</tt>'); }
175
 
sub do_cmd_function{
176
 
    return use_wrappers(@_[0], '<tt class="function">', '</tt>'); }
177
 
sub do_cmd_constant{
178
 
    return use_wrappers(@_[0], '<tt class="constant">', '</tt>'); }
179
 
sub do_cmd_member{
180
 
    return use_wrappers(@_[0], '<tt class="member">', '</tt>'); }
181
 
sub do_cmd_method{
182
 
    return use_wrappers(@_[0], '<tt class="method">', '</tt>'); }
183
 
sub do_cmd_cfunction{
184
 
    return use_wrappers(@_[0], '<tt class="cfunction">', '</tt>'); }
185
 
sub do_cmd_cdata{
186
 
    return use_wrappers(@_[0], '<tt class="cdata">', '</tt>'); }
187
 
sub do_cmd_ctype{
188
 
    return use_wrappers(@_[0], '<tt class="ctype">', '</tt>'); }
189
 
sub do_cmd_regexp{
190
 
    return use_wrappers(@_[0], '<tt class="regexp">', '</tt>'); }
191
 
sub do_cmd_character{
192
 
    return use_wrappers(@_[0], '"<tt class="character">', '</tt>"'); }
193
 
sub do_cmd_program{
194
 
    return use_wrappers(@_[0], '<b class="program">', '</b>'); }
195
 
sub do_cmd_programopt{
196
 
    return use_wrappers(@_[0], '<b class="programopt">', '</b>'); }
197
 
sub do_cmd_longprogramopt{
198
 
    # note that the --- will be later converted to -- by LaTeX2HTML
199
 
    return use_wrappers(@_[0], '<b class="programopt">---', '</b>'); }
200
 
sub do_cmd_email{
201
 
    return use_wrappers(@_[0], '<span class="email">', '</span>'); }
202
 
sub do_cmd_mimetype{
203
 
    return use_wrappers(@_[0], '<span class="mimetype">', '</span>'); }
204
 
sub do_cmd_var{
205
 
    return use_wrappers(@_[0], "<var>", "</var>"); }
206
 
sub do_cmd_dfn{
207
 
    return use_wrappers(@_[0], '<i class="dfn">', '</i>'); }
208
 
sub do_cmd_emph{
209
 
    return use_wrappers(@_[0], '<i>', '</i>'); }
210
 
sub do_cmd_file{
211
 
    return use_wrappers(@_[0], '<span class="file">', '</span>'); }
212
 
sub do_cmd_filenq{
213
 
    return do_cmd_file(@_[0]); }
214
 
sub do_cmd_samp{
215
 
    return use_wrappers(@_[0], '"<tt class="samp">', '</tt>"'); }
216
 
sub do_cmd_kbd{
217
 
    return use_wrappers(@_[0], '<kbd>', '</kbd>'); }
218
 
sub do_cmd_strong{
219
 
    return use_wrappers(@_[0], '<b>', '</b>'); }
220
 
sub do_cmd_textbf{
221
 
    return use_wrappers(@_[0], '<b>', '</b>'); }
222
 
sub do_cmd_textit{
223
 
    return use_wrappers(@_[0], '<i>', '</i>'); }
224
 
 
225
 
sub do_cmd_moreargs{
226
 
    return '...' . @_[0]; }
227
 
sub do_cmd_unspecified{
228
 
    return '...' . @_[0]; }
229
 
 
230
 
 
231
 
sub do_cmd_refmodule{
232
 
    # Insert the right magic to jump to the module definition.
233
 
    local($_) = @_;
234
 
    my $key = next_optional_argument();
235
 
    my $module = next_argument();
236
 
    $key = $module
237
 
        unless $key;
238
 
    return "<tt class='module'><a href='module-$key.html'>$module</a></tt>"
239
 
      . $_;
240
 
}
241
 
 
242
 
sub do_cmd_newsgroup{
243
 
    local($_) = @_;
244
 
    my $newsgroup = next_argument();
245
 
    my $icon = get_link_icon("news:$newsgroup");
246
 
    my $stuff = "<a class='newsgroup' href='news:$newsgroup'>"
247
 
      . "$newsgroup$icon</a>";
248
 
    return $stuff . $_;
249
 
}
250
 
 
251
 
sub do_cmd_envvar{
252
 
    local($_) = @_;
253
 
    my $envvar = next_argument();
254
 
    my($name,$aname,$ahref) = new_link_info();
255
 
    # The <tt> here is really to keep buildindex.py from making
256
 
    # the variable name case-insensitive.
257
 
    add_index_entry("environment variables!$envvar@<tt>$envvar</tt>",
258
 
                    $ahref);
259
 
    add_index_entry("$envvar (environment variable)", $ahref);
260
 
    $aname =~ s/<a/<a class="envvar"/;
261
 
    return "$aname$envvar</a>" . $_;
262
 
}
263
 
 
264
 
sub do_cmd_url{
265
 
    # use the URL as both text and hyperlink
266
 
    local($_) = @_;
267
 
    my $url = next_argument();
268
 
    my $icon = get_link_icon($url);
269
 
    $url =~ s/~/&#126;/g;
270
 
    return "<a class=\"url\" href=\"$url\">$url$icon</a>" . $_;
271
 
}
272
 
 
273
 
sub do_cmd_manpage{
274
 
    # two parameters:  \manpage{name}{section}
275
 
    local($_) = @_;
276
 
    my $page = next_argument();
277
 
    my $section = next_argument();
278
 
    return "<span class='manpage'><i>$page</i>($section)</span>" . $_;
279
 
}
280
 
 
281
 
$PEP_FORMAT = "http://python.sourceforge.net/peps/pep-XXXX.html";
282
 
$RFC_FORMAT = "http://www.ietf.org/rfc/rfcXXXX.txt";
283
 
 
284
 
sub get_rfc_url($$){
285
 
    my($rfcnum, $format) = @_;
286
 
    $rfcnum = sprintf("%04d", $rfcnum);
287
 
    $format = "$format";
288
 
    $format =~ s/XXXX/$rfcnum/;
289
 
    return $format;
290
 
}
291
 
 
292
 
sub do_cmd_pep{
293
 
    local($_) = @_;
294
 
    my $rfcnumber = next_argument();
295
 
    my $id = "rfcref-" . ++$global{'max_id'};
296
 
    my $href = get_rfc_url($rfcnumber, $PEP_FORMAT);
297
 
    my $icon = get_link_icon($href);
298
 
    # Save the reference
299
 
    my $nstr = gen_index_id("Python Enhancement Proposals!PEP $rfcnumber", '');
300
 
    $index{$nstr} .= make_half_href("$CURRENT_FILE#$id");
301
 
    return ("<a class=\"rfc\" name=\"$id\"\nhref=\"$href\">PEP $rfcnumber"
302
 
            . "$icon</a>" . $_);
303
 
}
304
 
 
305
 
sub do_cmd_rfc{
306
 
    local($_) = @_;
307
 
    my $rfcnumber = next_argument();
308
 
    my $id = "rfcref-" . ++$global{'max_id'};
309
 
    my $href = get_rfc_url($rfcnumber, $RFC_FORMAT);
310
 
    my $icon = get_link_icon($href);
311
 
    # Save the reference
312
 
    my $nstr = gen_index_id("RFC!RFC $rfcnumber", '');
313
 
    $index{$nstr} .= make_half_href("$CURRENT_FILE#$id");
314
 
    return ("<a class=\"rfc\" name=\"$id\"\nhref=\"$href\">RFC $rfcnumber"
315
 
            . "$icon</a>" . $_);
316
 
}
317
 
 
318
 
sub do_cmd_citetitle{
319
 
    local($_) = @_;
320
 
    my $url = next_optional_argument();
321
 
    my $title = next_argument();
322
 
    my $icon = get_link_icon($url);
323
 
    my $repl = '';
324
 
    if ($url) {
325
 
        $repl = ("<em class='citetitle'><a\n"
326
 
                 . " href='$url'\n"
327
 
                 . " title='$title'\n"
328
 
                 . " >$title$icon</a></em>");
329
 
    }
330
 
    else {
331
 
        $repl = "<em class='citetitle'\n >$title</em>";
332
 
    }
333
 
    return $repl . $_;
334
 
}
335
 
 
336
 
sub do_cmd_deprecated{
337
 
    # two parameters:  \deprecated{version}{whattodo}
338
 
    local($_) = @_;
339
 
    my $release = next_argument();
340
 
    my $reason = next_argument();
341
 
    return ('<div class="versionnote">'
342
 
            . "<b>Deprecated since release $release.</b>"
343
 
            . "\n$reason</div><p>"
344
 
            . $_);
345
 
}
346
 
 
347
 
sub do_cmd_versionadded{
348
 
    # one parameter:  \versionadded{version}
349
 
    local($_) = @_;
350
 
    my $release = next_argument();
351
 
    return ("\n<span class='versionnote'>New in version $release.</span>\n"
352
 
            . $_);
353
 
}
354
 
 
355
 
sub do_cmd_versionchanged{
356
 
    # one parameter:  \versionchanged{version}
357
 
    local($_) = @_;
358
 
    my $explanation = next_optional_argument();
359
 
    my $release = next_argument();
360
 
    my $text = "Changed in version $release.";
361
 
    if ($explanation) {
362
 
        $text = "Changed in version $release:\n$explanation.";
363
 
    }
364
 
    return "\n<span class='versionnote'>$text</span>\n" . $_;
365
 
}
366
 
 
367
 
#
368
 
# These function handle platform dependency tracking.
369
 
#
370
 
sub do_cmd_platform{
371
 
    local($_) = @_;
372
 
    my $platform = next_argument();
373
 
    $ModulePlatforms{"<tt class='module'>$THIS_MODULE</tt>"} = $platform;
374
 
    $platform = "Macintosh"
375
 
      if $platform eq 'Mac';
376
 
    return "\n<p class='availability'>Availability: <span"
377
 
      . "\n class='platform'>$platform</span>.</p>\n" . $_;
378
 
}
379
 
 
380
 
$IGNORE_PLATFORM_ANNOTATION = '';
381
 
sub do_cmd_ignorePlatformAnnotation{
382
 
    local($_) = @_;
383
 
    $IGNORE_PLATFORM_ANNOTATION = next_argument();
384
 
    return $_;
385
 
}
386
 
 
387
 
 
388
 
# index commands
389
 
 
390
 
$INDEX_SUBITEM = "";
391
 
 
392
 
sub get_indexsubitem{
393
 
    return $INDEX_SUBITEM ? " $INDEX_SUBITEM" : '';
394
 
}
395
 
 
396
 
sub do_cmd_setindexsubitem{
397
 
    local($_) = @_;
398
 
    $INDEX_SUBITEM = next_argument();
399
 
    return $_;
400
 
}
401
 
 
402
 
sub do_cmd_withsubitem{
403
 
    # We can't really do the right thing, because LaTeX2HTML doesn't
404
 
    # do things in the right order, but we need to at least strip this stuff
405
 
    # out, and leave anything that the second argument expanded out to.
406
 
    #
407
 
    local($_) = @_;
408
 
    my $oldsubitem = $INDEX_SUBITEM;
409
 
    $INDEX_SUBITEM = next_argument();
410
 
    my $stuff = next_argument();
411
 
    my $br_id = ++$globals{'max_id'};
412
 
    my $marker = "$O$br_id$C";
413
 
    return
414
 
      $stuff
415
 
      . "\\setindexsubitem$marker$oldsubitem$marker"
416
 
      . $_;
417
 
}
418
 
 
419
 
# This is the prologue macro which is required to start writing the
420
 
# mod\jobname.idx file; we can just ignore it.  (Defining this suppresses
421
 
# a warning that \makemodindex is unknown.)
422
 
#
423
 
sub do_cmd_makemodindex{ return @_[0]; }
424
 
 
425
 
# We're in the document subdirectory when this happens!
426
 
#
427
 
open(IDXFILE, '>index.dat') || die "\n$!\n";
428
 
open(INTLABELS, '>intlabels.pl') || die "\n$!\n";
429
 
print INTLABELS "%internal_labels = ();\n";
430
 
print INTLABELS "1;             # hack in case there are no entries\n\n";
431
 
 
432
 
# Using \0 for this is bad because we can't use common tools to work with the
433
 
# resulting files.  Things like grep can be useful with this stuff!
434
 
#
435
 
$IDXFILE_FIELD_SEP = "\1";
436
 
 
437
 
sub write_idxfile{
438
 
    my ($ahref, $str) = @_;
439
 
    print IDXFILE $ahref, $IDXFILE_FIELD_SEP, $str, "\n";
440
 
}
441
 
 
442
 
 
443
 
sub gen_link{
444
 
    my($node,$target) = @_;
445
 
    print INTLABELS "\$internal_labels{\"$target\"} = \"$URL/$node\";\n";
446
 
    return "<a href='$node#$target'>";
447
 
}
448
 
 
449
 
sub add_index_entry{
450
 
    # add an entry to the index structures; ignore the return value
451
 
    my($str,$ahref) = @_;
452
 
    $str = gen_index_id($str, '');
453
 
    $index{$str} .= $ahref;
454
 
    write_idxfile($ahref, $str);
455
 
}
456
 
 
457
 
sub new_link_info{
458
 
    my $name = "l2h-" . ++$globals{'max_id'};
459
 
    my $aname = "<a name='$name'>";
460
 
    my $ahref = gen_link($CURRENT_FILE, $name);
461
 
    return ($name, $aname, $ahref);
462
 
}
463
 
 
464
 
$IndexMacroPattern = '';
465
 
sub define_indexing_macro{
466
 
    my $count = @_;
467
 
    my $i = 0;
468
 
    for (; $i < $count; ++$i) {
469
 
        my $name = @_[$i];
470
 
        my $cmd = "idx_cmd_$name";
471
 
        die "\nNo function $cmd() defined!\n"
472
 
          if (!defined &$cmd);
473
 
        eval ("sub do_cmd_$name { return process_index_macros("
474
 
              . "\@_[0], '$name'); }");
475
 
        if (length($IndexMacroPattern) == 0) {
476
 
            $IndexMacroPattern = "$name";
477
 
        }
478
 
        else {
479
 
            $IndexMacroPattern .= "|$name";
480
 
        }
481
 
    }
482
 
}
483
 
 
484
 
$DEBUG_INDEXING = 0;
485
 
sub process_index_macros{
486
 
    local($_) = @_;
487
 
    my $cmdname = @_[1];        # This is what triggered us in the first place;
488
 
                                # we know it's real, so just process it.
489
 
    my($name,$aname,$ahref) = new_link_info();
490
 
    my $cmd = "idx_cmd_$cmdname";
491
 
    print "\nIndexing: \\$cmdname"
492
 
      if $DEBUG_INDEXING;
493
 
    &$cmd($ahref);              # modifies $_ and adds index entries
494
 
    while (/^[\s\n]*\\($IndexMacroPattern)</) {
495
 
        $cmdname = "$1";
496
 
        print " \\$cmdname"
497
 
          if $DEBUG_INDEXING;
498
 
        $cmd = "idx_cmd_$cmdname";
499
 
        if (!defined &$cmd) {
500
 
            last;
501
 
        }
502
 
        else {
503
 
            s/^[\s\n]*\\$cmdname//;
504
 
            &$cmd($ahref);
505
 
        }
506
 
    }
507
 
    if (/^[ \t\r\n]/) {
508
 
        $_ = substr($_, 1);
509
 
    }
510
 
    return "$aname$anchor_invisible_mark</a>" . $_;
511
 
}
512
 
 
513
 
define_indexing_macro('index');
514
 
sub idx_cmd_index{
515
 
    my $str = next_argument();
516
 
    add_index_entry("$str", @_[0]);
517
 
}
518
 
 
519
 
define_indexing_macro('kwindex');
520
 
sub idx_cmd_kwindex{
521
 
    my $str = next_argument();
522
 
    add_index_entry("<tt>$str</tt>!keyword", @_[0]);
523
 
    add_index_entry("keyword!<tt>$str</tt>", @_[0]);
524
 
}
525
 
 
526
 
define_indexing_macro('indexii');
527
 
sub idx_cmd_indexii{
528
 
    my $str1 = next_argument();
529
 
    my $str2 = next_argument();
530
 
    add_index_entry("$str1!$str2", @_[0]);
531
 
    add_index_entry("$str2!$str1", @_[0]);
532
 
}
533
 
 
534
 
define_indexing_macro('indexiii');
535
 
sub idx_cmd_indexiii{
536
 
    my $str1 = next_argument();
537
 
    my $str2 = next_argument();
538
 
    my $str3 = next_argument();
539
 
    add_index_entry("$str1!$str2 $str3", @_[0]);
540
 
    add_index_entry("$str2!$str3, $str1", @_[0]);
541
 
    add_index_entry("$str3!$str1 $str2", @_[0]);
542
 
}
543
 
 
544
 
define_indexing_macro('indexiv');
545
 
sub idx_cmd_indexiv{
546
 
    my $str1 = next_argument();
547
 
    my $str2 = next_argument();
548
 
    my $str3 = next_argument();
549
 
    my $str4 = next_argument();
550
 
    add_index_entry("$str1!$str2 $str3 $str4", @_[0]);
551
 
    add_index_entry("$str2!$str3 $str4, $str1", @_[0]);
552
 
    add_index_entry("$str3!$str4, $str1 $str2", @_[0]);
553
 
    add_index_entry("$str4!$$str1 $str2 $str3", @_[0]);
554
 
}
555
 
 
556
 
define_indexing_macro('ttindex');
557
 
sub idx_cmd_ttindex{
558
 
    my $str = next_argument();
559
 
    my $entry = $str . get_indexsubitem();
560
 
    add_index_entry($entry, @_[0]);
561
 
}
562
 
 
563
 
sub my_typed_index_helper{
564
 
    my($word,$ahref) = @_;
565
 
    my $str = next_argument();
566
 
    add_index_entry("$str $word", $ahref);
567
 
    add_index_entry("$word!$str", $ahref);
568
 
}
569
 
 
570
 
define_indexing_macro('stindex', 'opindex', 'exindex', 'obindex');
571
 
sub idx_cmd_stindex{ my_typed_index_helper('statement', @_[0]); }
572
 
sub idx_cmd_opindex{ my_typed_index_helper('operator', @_[0]); }
573
 
sub idx_cmd_exindex{ my_typed_index_helper('exception', @_[0]); }
574
 
sub idx_cmd_obindex{ my_typed_index_helper('object', @_[0]); }
575
 
 
576
 
define_indexing_macro('bifuncindex');
577
 
sub idx_cmd_bifuncindex{
578
 
    my $str = next_argument();
579
 
    add_index_entry("<tt class='function'>$str()</tt> (built-in function)",
580
 
                    @_[0]);
581
 
}
582
 
 
583
 
 
584
 
sub make_mod_index_entry{
585
 
    my($str,$define) = @_;
586
 
    my($name,$aname,$ahref) = new_link_info();
587
 
    # equivalent of add_index_entry() using $define instead of ''
588
 
    $ahref =~ s/\#[-_a-zA-Z0-9]*\"/\"/
589
 
      if ($define eq 'DEF');
590
 
    $str = gen_index_id($str, $define);
591
 
    $index{$str} .= $ahref;
592
 
    write_idxfile($ahref, $str);
593
 
 
594
 
    if ($define eq 'DEF') {
595
 
        # add to the module index
596
 
        $str =~ /(<tt.*<\/tt>)/;
597
 
        my $nstr = $1;
598
 
        $Modules{$nstr} .= $ahref;
599
 
    }
600
 
    return "$aname$anchor_invisible_mark2</a>";
601
 
}
602
 
 
603
 
 
604
 
$THIS_MODULE = '';
605
 
$THIS_CLASS = '';
606
 
 
607
 
sub define_module{
608
 
    my($word,$name) = @_;
609
 
    my $section_tag = join('', @curr_sec_id);
610
 
    if ($word ne "built-in" && $word ne "extension"
611
 
        && $word ne "standard" && $word ne "") {
612
 
        write_warnings("Bad module type '$word'"
613
 
                       . " for \\declaremodule (module $name)");
614
 
        $word = "";
615
 
    }
616
 
    $word = "$word " if $word;
617
 
    $THIS_MODULE = "$name";
618
 
    $INDEX_SUBITEM = "(in module $name)";
619
 
    print "[$name]";
620
 
    return make_mod_index_entry(
621
 
        "<tt class='module'>$name</tt> (${word}module)", 'DEF');
622
 
}
623
 
 
624
 
sub my_module_index_helper{
625
 
    local($word, $_) = @_;
626
 
    my $name = next_argument();
627
 
    return define_module($word, $name) . $_;
628
 
}
629
 
 
630
 
sub do_cmd_modindex{ return my_module_index_helper('', @_); }
631
 
sub do_cmd_bimodindex{ return my_module_index_helper('built-in', @_); }
632
 
sub do_cmd_exmodindex{ return my_module_index_helper('extension', @_); }
633
 
sub do_cmd_stmodindex{ return my_module_index_helper('standard', @_); }
634
 
 
635
 
sub ref_module_index_helper{
636
 
    my($word, $ahref) = @_;
637
 
    my $str = next_argument();
638
 
    $word = "$word " if $word;
639
 
    $str = "<tt class='module'>$str</tt> (${word}module)";
640
 
    # can't use add_index_entry() since the 2nd arg to gen_index_id() is used;
641
 
    # just inline it all here
642
 
    $str = gen_index_id($str, 'REF');
643
 
    $index{$str} .= $ahref;
644
 
    write_idxfile($ahref, $str);
645
 
}
646
 
 
647
 
# these should be adjusted a bit....
648
 
define_indexing_macro('refmodindex', 'refbimodindex',
649
 
                      'refexmodindex', 'refstmodindex');
650
 
sub idx_cmd_refmodindex{ return ref_module_index_helper('', @_); }
651
 
sub idx_cmd_refbimodindex{ return ref_module_index_helper('built-in', @_); }
652
 
sub idx_cmd_refexmodindex{ return ref_module_index_helper('extension', @_); }
653
 
sub idx_cmd_refstmodindex{ return ref_module_index_helper('standard', @_); }
654
 
 
655
 
sub do_cmd_nodename{ return do_cmd_label(@_); }
656
 
 
657
 
sub init_myformat{
658
 
    $anchor_invisible_mark = '&nbsp;';
659
 
    $anchor_invisible_mark2 = '';
660
 
    $anchor_mark = '';
661
 
    $icons{'anchor_mark'} = '';
662
 
}
663
 
init_myformat();
664
 
 
665
 
# Create an index entry, but include the string in the target anchor
666
 
# instead of the dummy filler.
667
 
#
668
 
sub make_str_index_entry{
669
 
    my($str) = @_;
670
 
    my($name,$aname,$ahref) = new_link_info();
671
 
    add_index_entry($str, $ahref);
672
 
    return "$aname$str</a>";
673
 
}
674
 
 
675
 
$REFCOUNTS_LOADED = 0;
676
 
 
677
 
sub load_refcounts{
678
 
    $REFCOUNTS_LOADED = 1;
679
 
 
680
 
    my $myname, $mydir, $myext;
681
 
    ($myname, $mydir, $myext) = fileparse(__FILE__, '\..*');
682
 
    chop $mydir;                        # remove trailing '/'
683
 
    ($myname, $mydir, $myext) = fileparse($mydir, '\..*');
684
 
    chop $mydir;                        # remove trailing '/'
685
 
    $mydir = getcwd() . "$dd$mydir"
686
 
      unless $mydir =~ s|^/|/|;
687
 
    local $_;
688
 
    my $filename = "$mydir${dd}api${dd}refcounts.dat";
689
 
    open(REFCOUNT_FILE, "<$filename") || die "\n$!\n";
690
 
    print "[loading API refcount data]";
691
 
    while (<REFCOUNT_FILE>) {
692
 
        if (/([a-zA-Z0-9_]+):PyObject\*:([a-zA-Z0-9_]*):(0|[-+]1|null):(.*)$/) {
693
 
            my($func, $param, $count, $comment) = ($1, $2, $3, $4);
694
 
            #print "\n$func($param) --> $count";
695
 
            $REFCOUNTS{"$func:$param"} = $count;
696
 
        }
697
 
    }
698
 
}
699
 
 
700
 
sub get_refcount{
701
 
    my ($func, $param) = @_;
702
 
    load_refcounts()
703
 
        unless $REFCOUNTS_LOADED;
704
 
    return $REFCOUNTS{"$func:$param"};
705
 
}
706
 
 
707
 
sub do_env_cfuncdesc{
708
 
    local($_) = @_;
709
 
    my $return_type = next_argument();
710
 
    my $function_name = next_argument();
711
 
    my $arg_list = next_argument();
712
 
    my $idx = make_str_index_entry(
713
 
        "<tt class='cfunction'>$function_name()</tt>" . get_indexsubitem());
714
 
    $idx =~ s/ \(.*\)//;
715
 
    $idx =~ s/\(\)//;           # ???? - why both of these?
716
 
    my $result_rc = get_refcount($function_name, '');
717
 
    my $rcinfo = '';
718
 
    if ($result_rc eq '+1') {
719
 
        $rcinfo = 'New reference';
720
 
    }
721
 
    elsif ($result_rc eq '0') {
722
 
        $rcinfo = 'Borrowed reference';
723
 
    }
724
 
    elsif ($result_rc eq 'null') {
725
 
        $rcinfo = 'Always <tt class="constant">NULL</tt>';
726
 
    }
727
 
    if ($rcinfo ne '') {
728
 
        $rcinfo = (  "\n<div class=\"refcount-info\">"
729
 
                   . "\n  <span class=\"label\">Return value:</span>"
730
 
                   . "\n  <span class=\"value\">$rcinfo.</span>"
731
 
                   . "\n</div>");
732
 
    }
733
 
    return "<dl><dt>$return_type <b>$idx</b>(<var>$arg_list</var>)\n<dd>"
734
 
           . $rcinfo
735
 
           . $_
736
 
           . '</dl>';
737
 
}
738
 
 
739
 
sub do_env_csimplemacrodesc{
740
 
    local($_) = @_;
741
 
    my $name = next_argument();
742
 
    my $idx = make_str_index_entry("<tt class='macro'>$name</tt>");
743
 
    return "<dl><dt><b>$idx</b>\n<dd>"
744
 
           . $_
745
 
           . '</dl>'
746
 
}
747
 
 
748
 
sub do_env_ctypedesc{
749
 
    local($_) = @_;
750
 
    my $index_name = next_optional_argument();
751
 
    my $type_name = next_argument();
752
 
    $index_name = $type_name
753
 
      unless $index_name;
754
 
    my($name,$aname,$ahref) = new_link_info();
755
 
    add_index_entry("<tt class='ctype'>$index_name</tt> (C type)", $ahref);
756
 
    return "<dl><dt><b><tt class='ctype'>$aname$type_name</a></tt></b>\n<dd>"
757
 
           . $_
758
 
           . '</dl>'
759
 
}
760
 
 
761
 
sub do_env_cvardesc{
762
 
    local($_) = @_;
763
 
    my $var_type = next_argument();
764
 
    my $var_name = next_argument();
765
 
    my $idx = make_str_index_entry("<tt class='cdata'>$var_name</tt>"
766
 
                                   . get_indexsubitem());
767
 
    $idx =~ s/ \(.*\)//;
768
 
    return "<dl><dt>$var_type <b>$idx</b>\n"
769
 
           . '<dd>'
770
 
           . $_
771
 
           . '</dl>';
772
 
}
773
 
 
774
 
sub convert_args($){
775
 
    local($IN_DESC_HANDLER) = 1;
776
 
    local($_) = @_;
777
 
    return translate_commands($_);
778
 
}
779
 
 
780
 
sub do_env_funcdesc{
781
 
    local($_) = @_;
782
 
    my $function_name = next_argument();
783
 
    my $arg_list = convert_args(next_argument());
784
 
    my $idx = make_str_index_entry("<tt class='function'>$function_name()</tt>"
785
 
                                   . get_indexsubitem());
786
 
    $idx =~ s/ \(.*\)//;
787
 
    $idx =~ s/\(\)<\/tt>/<\/tt>/;
788
 
    return "<dl><dt><b>$idx</b>(<var>$arg_list</var>)\n<dd>" . $_ . '</dl>';
789
 
}
790
 
 
791
 
sub do_env_funcdescni{
792
 
    local($_) = @_;
793
 
    my $function_name = next_argument();
794
 
    my $arg_list = convert_args(next_argument());
795
 
    return "<dl><dt><b><tt class='function'>$function_name</tt></b>"
796
 
      . "(<var>$arg_list</var>)\n"
797
 
      . '<dd>'
798
 
      . $_
799
 
      . '</dl>';
800
 
}
801
 
 
802
 
sub do_cmd_funcline{
803
 
    local($_) = @_;
804
 
    my $function_name = next_argument();
805
 
    my $arg_list = convert_args(next_argument());
806
 
    my $prefix = "<tt class='function'>$function_name()</tt>";
807
 
    my $idx = make_str_index_entry($prefix . get_indexsubitem());
808
 
    $prefix =~ s/\(\)//;
809
 
 
810
 
    return "<dt><b>$prefix</b>(<var>$arg_list</var>)\n<dd>" . $_;
811
 
}
812
 
 
813
 
sub do_cmd_funclineni{
814
 
    local($_) = @_;
815
 
    my $function_name = next_argument();
816
 
    my $arg_list = convert_args(next_argument());
817
 
    my $prefix = "<tt class='function'>$function_name</tt>";
818
 
 
819
 
    return "<dt><b>$prefix</b>(<var>$arg_list</var>)\n<dd>" . $_;
820
 
}
821
 
 
822
 
# Change this flag to index the opcode entries.  I don't think it's very
823
 
# useful to index them, since they're only presented to describe the dis
824
 
# module.
825
 
#
826
 
$INDEX_OPCODES = 0;
827
 
 
828
 
sub do_env_opcodedesc{
829
 
    local($_) = @_;
830
 
    my $opcode_name = next_argument();
831
 
    my $arg_list = next_argument();
832
 
    my $idx;
833
 
    if ($INDEX_OPCODES) {
834
 
        $idx = make_str_index_entry("<tt class='opcode'>$opcode_name</tt>"
835
 
                                    . " (byte code instruction)");
836
 
        $idx =~ s/ \(byte code instruction\)//;
837
 
    }
838
 
    else {
839
 
        $idx = "<tt class='opcode'>$opcode_name</tt>";
840
 
    }
841
 
    my $stuff = "<dl><dt><b>$idx</b>";
842
 
    if ($arg_list) {
843
 
        $stuff .= "&nbsp;&nbsp;&nbsp;&nbsp;<var>$arg_list</var>";
844
 
    }
845
 
    return $stuff . "\n<dd>" . $_ . '</dl>';
846
 
}
847
 
 
848
 
sub do_env_datadesc{
849
 
    local($_) = @_;
850
 
    my $dataname = next_argument();
851
 
    my $idx = make_str_index_entry("<tt>$dataname</tt>" . get_indexsubitem());
852
 
    $idx =~ s/ \(.*\)//;
853
 
    return "<dl><dt><b>$idx</b>\n<dd>"
854
 
           . $_
855
 
           . '</dl>';
856
 
}
857
 
 
858
 
sub do_env_datadescni{
859
 
    local($_) = @_;
860
 
    my $idx = next_argument();
861
 
    if (! $STRING_INDEX_TT) {
862
 
        $idx = "<tt>$idx</tt>";
863
 
    }
864
 
    return "<dl><dt><b>$idx</b>\n<dd>" . $_ . '</dl>';
865
 
}
866
 
 
867
 
sub do_cmd_dataline{
868
 
    local($_) = @_;
869
 
    my $data_name = next_argument();
870
 
    my $idx = make_str_index_entry("<tt>$data_name</tt>" . get_indexsubitem());
871
 
    $idx =~ s/ \(.*\)//;
872
 
    return "<dt><b>$idx</b><dd>" . $_;
873
 
}
874
 
 
875
 
sub do_cmd_datalineni{
876
 
    local($_) = @_;
877
 
    my $data_name = next_argument();
878
 
    return "<dt><b><tt>$data_name</tt></b><dd>" . $_;
879
 
}
880
 
 
881
 
sub do_env_excdesc{
882
 
    local($_) = @_;
883
 
    my $excname = next_argument();
884
 
    my $idx = make_str_index_entry("<tt class='exception'>$excname</tt>");
885
 
    return "<dl><dt><b>exception $idx</b>\n<dd>" . $_ . '</dl>'
886
 
}
887
 
 
888
 
sub do_env_fulllineitems{ return do_env_itemize(@_); }
889
 
 
890
 
 
891
 
sub handle_classlike_descriptor{
892
 
    local($_, $what) = @_;
893
 
    $THIS_CLASS = next_argument();
894
 
    my $arg_list = convert_args(next_argument());
895
 
    $idx = make_str_index_entry(
896
 
                "<tt class='$what'>$THIS_CLASS</tt> ($what in $THIS_MODULE)" );
897
 
    $idx =~ s/ \(.*\)//;
898
 
    return ("<dl><dt><b>$what $idx</b>(<var>$arg_list</var>)\n<dd>"
899
 
            . $_
900
 
            . '</dl>');
901
 
}
902
 
 
903
 
sub do_env_classdesc{
904
 
    return handle_classlike_descriptor(@_[0], "class");
905
 
}
906
 
 
907
 
sub do_env_excclassdesc{
908
 
    return handle_classlike_descriptor(@_[0], "exception");
909
 
}
910
 
 
911
 
 
912
 
sub do_env_methoddesc{
913
 
    local($_) = @_;
914
 
    my $class_name = next_optional_argument();
915
 
    $class_name = $THIS_CLASS
916
 
        unless $class_name;
917
 
    my $method = next_argument();
918
 
    my $arg_list = convert_args(next_argument());
919
 
    my $extra = '';
920
 
    if ($class_name) {
921
 
        $extra = " ($class_name method)";
922
 
    }
923
 
    my $idx = make_str_index_entry("<tt class='method'>$method()</tt>$extra");
924
 
    $idx =~ s/ \(.*\)//;
925
 
    $idx =~ s/\(\)//;
926
 
    return "<dl><dt><b>$idx</b>(<var>$arg_list</var>)\n<dd>" . $_ . '</dl>';
927
 
}
928
 
 
929
 
 
930
 
sub do_cmd_methodline{
931
 
    local($_) = @_;
932
 
    my $class_name = next_optional_argument();
933
 
    $class_name = $THIS_CLASS
934
 
        unless $class_name;
935
 
    my $method = next_argument();
936
 
    my $arg_list = convert_args(next_argument());
937
 
    my $extra = '';
938
 
    if ($class_name) {
939
 
        $extra = " ($class_name method)";
940
 
    }
941
 
    my $idx = make_str_index_entry("<tt class='method'>$method()</tt>$extra");
942
 
    $idx =~ s/ \(.*\)//;
943
 
    $idx =~ s/\(\)//;
944
 
    return "<dt><b>$idx</b>(<var>$arg_list</var>)\n<dd>"
945
 
           . $_;
946
 
}
947
 
 
948
 
 
949
 
sub do_cmd_methodlineni{
950
 
    local($_) = @_;
951
 
    next_optional_argument();
952
 
    my $method = next_argument();
953
 
    my $arg_list = convert_args(next_argument());
954
 
    return "<dt><b>$method</b>(<var>$arg_list</var>)\n<dd>"
955
 
           . $_;
956
 
}
957
 
 
958
 
sub do_env_methoddescni{
959
 
    local($_) = @_;
960
 
    next_optional_argument();
961
 
    my $method = next_argument();
962
 
    my $arg_list = convert_args(next_argument());
963
 
    return "<dl><dt><b>$method</b>(<var>$arg_list</var>)\n<dd>"
964
 
           . $_
965
 
           . '</dl>';
966
 
}
967
 
 
968
 
 
969
 
sub do_env_memberdesc{
970
 
    local($_) = @_;
971
 
    my $class = next_optional_argument();
972
 
    my $member = next_argument();
973
 
    $class = $THIS_CLASS
974
 
        unless $class;
975
 
    my $extra = '';
976
 
    $extra = " ($class attribute)"
977
 
        if ($class ne '');
978
 
    my $idx = make_str_index_entry("<tt class='member'>$member</tt>$extra");
979
 
    $idx =~ s/ \(.*\)//;
980
 
    $idx =~ s/\(\)//;
981
 
    return "<dl><dt><b>$idx</b>\n<dd>" . $_ . '</dl>';
982
 
}
983
 
 
984
 
 
985
 
sub do_cmd_memberline{
986
 
    local($_) = @_;
987
 
    my $class = next_optional_argument();
988
 
    my $member = next_argument();
989
 
    $class = $THIS_CLASS
990
 
        unless $class;
991
 
    my $extra = '';
992
 
    $extra = " ($class attribute)"
993
 
        if ($class ne '');
994
 
    my $idx = make_str_index_entry("<tt class='member'>$member</tt>$extra");
995
 
    $idx =~ s/ \(.*\)//;
996
 
    $idx =~ s/\(\)//;
997
 
    return "<dt><b>$idx</b><dd>" . $_;
998
 
}
999
 
 
1000
 
sub do_env_memberdescni{
1001
 
    local($_) = @_;
1002
 
    next_optional_argument();
1003
 
    my $member = next_argument();
1004
 
    return "<dl><dt><b><tt class='member'>$member</tt></b>\n<dd>"
1005
 
           . $_
1006
 
           . '</dl>';
1007
 
}
1008
 
 
1009
 
 
1010
 
sub do_cmd_memberlineni{
1011
 
    local($_) = @_;
1012
 
    next_optional_argument();
1013
 
    my $member = next_argument();
1014
 
    return "<dt><b><tt class='member'>$member</tt></b><dd>" . $_;
1015
 
}
1016
 
 
1017
 
@col_aligns = ('<td>', '<td>', '<td>', '<td>');
1018
 
 
1019
 
sub fix_font{
1020
 
    # do a little magic on a font name to get the right behavior in the first
1021
 
    # column of the output table
1022
 
    my $font = @_[0];
1023
 
    if ($font eq 'textrm') {
1024
 
        $font = '';
1025
 
    }
1026
 
    elsif ($font eq 'file' || $font eq 'filenq') {
1027
 
        $font = 'tt class="file"';
1028
 
    }
1029
 
    elsif ($font eq 'member') {
1030
 
        $font = 'tt class="member"';
1031
 
    }
1032
 
    elsif ($font eq 'class') {
1033
 
        $font = 'tt class="class"';
1034
 
    }
1035
 
    elsif ($font eq 'constant') {
1036
 
        $font = 'tt class="constant"';
1037
 
    }
1038
 
    elsif ($font eq 'kbd') {
1039
 
        $font = 'kbd';
1040
 
    }
1041
 
    elsif ($font eq 'programopt') {
1042
 
        $font = 'b';
1043
 
    }
1044
 
    elsif ($font eq 'exception') {
1045
 
        $font = 'tt class="exception"';
1046
 
    }
1047
 
    return $font;
1048
 
}
1049
 
 
1050
 
sub figure_column_alignment{
1051
 
    my $a = @_[0];
1052
 
    my $mark = substr($a, 0, 1);
1053
 
    my $r = '';
1054
 
    if ($mark eq 'c')
1055
 
      { $r = ' align="center"'; }
1056
 
    elsif ($mark eq 'r')
1057
 
      { $r = ' align="right"'; }
1058
 
    elsif ($mark eq 'l')
1059
 
      { $r = ' align="left"'; }
1060
 
    elsif ($mark eq 'p')
1061
 
      { $r = ' align="left"'; }
1062
 
    return $r;
1063
 
}
1064
 
 
1065
 
sub setup_column_alignments{
1066
 
    local($_) = @_;
1067
 
    my($s1,$s2,$s3,$s4) = split(/[|]/,$_);
1068
 
    my $a1 = figure_column_alignment($s1);
1069
 
    my $a2 = figure_column_alignment($s2);
1070
 
    my $a3 = figure_column_alignment($s3);
1071
 
    my $a4 = figure_column_alignment($s4);
1072
 
    $col_aligns[0] = "<td$a1 valign=\"baseline\">";
1073
 
    $col_aligns[1] = "<td$a2>";
1074
 
    $col_aligns[2] = "<td$a3>";
1075
 
    $col_aligns[3] = "<td$a4>";
1076
 
    # return the aligned header start tags
1077
 
    return ("<th$a1>", "<th$a2>", "<th$a3>", "<th$a4>");
1078
 
}
1079
 
 
1080
 
sub get_table_col1_fonts{
1081
 
    my $font = $globals{'lineifont'};
1082
 
    my ($sfont,$efont) = ('', '');
1083
 
    if ($font) {
1084
 
        $sfont = "<$font>";
1085
 
        $efont = "</$font>";
1086
 
        $efont =~ s/ .*>/>/;
1087
 
    }
1088
 
    return ($sfont, $efont);
1089
 
}
1090
 
 
1091
 
sub do_env_tableii{
1092
 
    local($_) = @_;
1093
 
    my($th1,$th2,$th3,$th4) = setup_column_alignments(next_argument());
1094
 
    my $font = fix_font(next_argument());
1095
 
    my $h1 = next_argument();
1096
 
    my $h2 = next_argument();
1097
 
    s/[\s\n]+//;
1098
 
    $globals{'lineifont'} = $font;
1099
 
    my $a1 = $col_aligns[0];
1100
 
    my $a2 = $col_aligns[1];
1101
 
    s/\\lineii</\\lineii[$a1|$a2]</g;
1102
 
    return '<table border align="center" style="border-collapse: collapse">'
1103
 
           . "\n  <thead>"
1104
 
           . "\n    <tr class=\"tableheader\">"
1105
 
           . "\n      $th1<b>$h1</b>\&nbsp;</th>"
1106
 
           . "\n      $th2<b>$h2</b>\&nbsp;</th>"
1107
 
           . "\n      </tr>"
1108
 
           . "\n    </thead>"
1109
 
           . "\n  <tbody valign='baseline'>"
1110
 
           . $_
1111
 
           . "\n    </tbody>"
1112
 
           . "\n</table>";
1113
 
}
1114
 
 
1115
 
sub do_env_longtableii{
1116
 
    return do_env_tableii(@_);
1117
 
}
1118
 
 
1119
 
sub do_cmd_lineii{
1120
 
    local($_) = @_;
1121
 
    my $aligns = next_optional_argument();
1122
 
    my $c1 = next_argument();
1123
 
    my $c2 = next_argument();
1124
 
    s/[\s\n]+//;
1125
 
    my($sfont,$efont) = get_table_col1_fonts();
1126
 
    $c2 = '&nbsp;' if ($c2 eq '');
1127
 
    my($c1align,$c2align) = split('\|', $aligns);
1128
 
    my $padding = '';
1129
 
    if ($c1align =~ /align="right"/ || $c1 eq '') {
1130
 
        $padding = '&nbsp;';
1131
 
    }
1132
 
    return "\n    <tr>$c1align$sfont$c1$efont$padding</td>\n"
1133
 
           . "        $c2align$c2</td>"
1134
 
           . $_;
1135
 
}
1136
 
 
1137
 
sub do_env_tableiii{
1138
 
    local($_) = @_;
1139
 
    my($th1,$th2,$th3,$th4) = setup_column_alignments(next_argument());
1140
 
    my $font = fix_font(next_argument());
1141
 
    my $h1 = next_argument();
1142
 
    my $h2 = next_argument();
1143
 
    my $h3 = next_argument();
1144
 
    s/[\s\n]+//;
1145
 
    $globals{'lineifont'} = $font;
1146
 
    my $a1 = $col_aligns[0];
1147
 
    my $a2 = $col_aligns[1];
1148
 
    my $a3 = $col_aligns[2];
1149
 
    s/\\lineiii</\\lineiii[$a1|$a2|$a3]</g;
1150
 
    return '<table border align="center" style="border-collapse: collapse">'
1151
 
           . "\n  <thead>"
1152
 
           . "\n    <tr class=\"tableheader\">"
1153
 
           . "\n      $th1<b>$h1</b>\&nbsp;</th>"
1154
 
           . "\n      $th2<b>$h2</b>\&nbsp;</th>"
1155
 
           . "\n      $th3<b>$h3</b>\&nbsp;</th>"
1156
 
           . "\n      </tr>"
1157
 
           . "\n    </thead>"
1158
 
           . "\n  <tbody valign='baseline'>"
1159
 
           . $_
1160
 
           . "\n    </tbody>"
1161
 
           . "\n</table>";
1162
 
}
1163
 
 
1164
 
sub do_env_longtableiii{
1165
 
    return do_env_tableiii(@_);
1166
 
}
1167
 
 
1168
 
sub do_cmd_lineiii{
1169
 
    local($_) = @_;
1170
 
    my $aligns = next_optional_argument();
1171
 
    my $c1 = next_argument();
1172
 
    my $c2 = next_argument(); 
1173
 
    my $c3 = next_argument();
1174
 
    s/[\s\n]+//;
1175
 
    my($sfont,$efont) = get_table_col1_fonts();
1176
 
    $c3 = '&nbsp;' if ($c3 eq '');
1177
 
    my($c1align,$c2align,$c3align) = split('\|', $aligns);
1178
 
    my $padding = '';
1179
 
    if ($c1align =~ /align="right"/ || $c1 eq '') {
1180
 
        $padding = '&nbsp;';
1181
 
    }
1182
 
    return "\n    <tr>$c1align$sfont$c1$efont$padding</td>\n"
1183
 
           . "        $c2align$c2</td>\n"
1184
 
           . "        $c3align$c3</td>"
1185
 
           . $_;
1186
 
}
1187
 
 
1188
 
sub do_env_tableiv{
1189
 
    local($_) = @_;
1190
 
    my($th1,$th2,$th3,$th4) = setup_column_alignments(next_argument());
1191
 
    my $font = fix_font(next_argument());
1192
 
    my $h1 = next_argument();
1193
 
    my $h2 = next_argument();
1194
 
    my $h3 = next_argument();
1195
 
    my $h4 = next_argument();
1196
 
    s/[\s\n]+//;
1197
 
    $globals{'lineifont'} = $font;
1198
 
    my $a1 = $col_aligns[0];
1199
 
    my $a2 = $col_aligns[1];
1200
 
    my $a3 = $col_aligns[2];
1201
 
    my $a4 = $col_aligns[3];
1202
 
    s/\\lineiv</\\lineiv[$a1|$a2|$a3|$a4]</g;
1203
 
    return '<table border align="center" style="border-collapse: collapse">'
1204
 
           . "\n  <thead>"
1205
 
           . "\n    <tr class=\"tableheader\">"
1206
 
           . "\n      $th1<b>$h1</b>\&nbsp;</th>"
1207
 
           . "\n      $th2<b>$h2</b>\&nbsp;</th>"
1208
 
           . "\n      $th3<b>$h3</b>\&nbsp;</th>"
1209
 
           . "\n      $th4<b>$h4</b>\&nbsp;</th>"
1210
 
           . "\n      </tr>"
1211
 
           . "\n    </thead>"
1212
 
           . "\n  <tbody valign='baseline'>"
1213
 
           . $_
1214
 
           . "\n    </tbody>"
1215
 
           . "\n</table>";
1216
 
}
1217
 
 
1218
 
sub do_env_longtableiv{
1219
 
    return do_env_tableiv(@_);
1220
 
}
1221
 
 
1222
 
sub do_cmd_lineiv{
1223
 
    local($_) = @_;
1224
 
    my $aligns = next_optional_argument();
1225
 
    my $c1 = next_argument();
1226
 
    my $c2 = next_argument(); 
1227
 
    my $c3 = next_argument();
1228
 
    my $c4 = next_argument();
1229
 
    s/[\s\n]+//;
1230
 
    my($sfont,$efont) = get_table_col1_fonts();
1231
 
    $c4 = '&nbsp;' if ($c4 eq '');
1232
 
    my($c1align,$c2align,$c3align,$c4align) = split('\|', $aligns);
1233
 
    my $padding = '';
1234
 
    if ($c1align =~ /align="right"/ || $c1 eq '') {
1235
 
        $padding = '&nbsp;';
1236
 
    }
1237
 
    return "\n    <tr>$c1align$sfont$c1$efont$padding</td>\n"
1238
 
           . "        $c2align$c2</td>\n"
1239
 
           . "        $c3align$c3</td>\n"
1240
 
           . "        $c4align$c4</td>"
1241
 
           . $_;
1242
 
}
1243
 
 
1244
 
 
1245
 
# These can be used to control the title page appearance;
1246
 
# they need a little bit of documentation.
1247
 
#
1248
 
# If $TITLE_PAGE_GRAPHIC is set, it should be the name of a file in the
1249
 
# $ICONSERVER directory, or include path information (other than "./").  The
1250
 
# default image type will be assumed if an extension is not provided.
1251
 
#
1252
 
# If specified, the "title page" will contain two colums: one containing the
1253
 
# title/author/etc., and the other containing the graphic.  Use the other
1254
 
# four variables listed here to control specific details of the layout; all
1255
 
# are optional.
1256
 
#
1257
 
# $TITLE_PAGE_GRAPHIC = "my-company-logo";
1258
 
# $TITLE_PAGE_GRAPHIC_COLWIDTH = "30%";
1259
 
# $TITLE_PAGE_GRAPHIC_WIDTH = 150;
1260
 
# $TITLE_PAGE_GRAPHIC_HEIGHT = 150;
1261
 
# $TITLE_PAGE_GRAPHIC_ON_RIGHT = 0;
1262
 
 
1263
 
sub make_my_titlepage() {
1264
 
    my $the_title = "";
1265
 
    if ($t_title) {
1266
 
        $the_title .= "\n<h1>$t_title</h1>";
1267
 
    }
1268
 
    else {
1269
 
        write_warnings("\nThis document has no title.");
1270
 
    }
1271
 
    if ($t_author) {
1272
 
        if ($t_authorURL) {
1273
 
            my $href = translate_commands($t_authorURL);
1274
 
            $href = make_named_href('author', $href,
1275
 
                                    "<b><font size='+2'>$t_author</font></b>");
1276
 
            $the_title .= "\n<p>$href</p>";
1277
 
        }
1278
 
        else {
1279
 
            $the_title .= ("\n<p><b><font size='+2'>$t_author</font></b></p>");
1280
 
        }
1281
 
    }
1282
 
    else {
1283
 
        write_warnings("\nThere is no author for this document.");
1284
 
    }
1285
 
    if ($t_institute) {
1286
 
        $the_title .= "\n<p>$t_institute</p>";
1287
 
    }
1288
 
    if ($DEVELOPER_ADDRESS) {
1289
 
        $the_title .= "\n<p>$DEVELOPER_ADDRESS</p>";
1290
 
    }
1291
 
    if ($t_affil) {
1292
 
        $the_title .= "\n<p><i>$t_affil</i></p>";
1293
 
    }
1294
 
    if ($t_date) {
1295
 
        $the_title .= "\n<p>";
1296
 
        if ($PACKAGE_VERSION) {
1297
 
            $the_title .= "<strong>Release $PACKAGE_VERSION</strong><br>\n";
1298
 
        }
1299
 
        $the_title .= "<strong>$t_date</strong></p>"
1300
 
    }
1301
 
    if ($t_address) {
1302
 
        $the_title .= "\n<p>$t_address</p>";
1303
 
    }
1304
 
    else {
1305
 
        $the_title .= "\n<p>";
1306
 
    }
1307
 
    if ($t_email) {
1308
 
        $the_title .= "\n<p>$t_email</p>";
1309
 
    }
1310
 
    return $the_title;
1311
 
}
1312
 
 
1313
 
sub make_my_titlegraphic() {
1314
 
    my $filename = make_icon_filename($TITLE_PAGE_GRAPHIC);
1315
 
    my $graphic = "<td class=\"titlegraphic\"";
1316
 
    $graphic .= " width=\"$TITLE_PAGE_GRAPHIC_COLWIDTH\""
1317
 
      if ($TITLE_PAGE_GRAPHIC_COLWIDTH);
1318
 
    $graphic .= "><img";
1319
 
    $graphic .= " width=\"$TITLE_PAGE_GRAPHIC_WIDTH\""
1320
 
      if ($TITLE_PAGE_GRAPHIC_WIDTH);
1321
 
    $graphic .= " height=\"$TITLE_PAGE_GRAPHIC_HEIGHT\""
1322
 
      if ($TITLE_PAGE_GRAPHIC_HEIGHT);
1323
 
    $graphic .= "\n  src=\"$filename\"></td>\n";
1324
 
    return $graphic;
1325
 
}
1326
 
 
1327
 
sub do_cmd_maketitle {
1328
 
    local($_) = @_;
1329
 
    my $the_title = "\n<div class=\"titlepage\">";
1330
 
    if ($TITLE_PAGE_GRAPHIC) {
1331
 
        if ($TITLE_PAGE_GRAPHIC_ON_RIGHT) {
1332
 
            $the_title .= ("\n<table border=\"0\" width=\"100%\">"
1333
 
                           . "<tr align=\"right\">\n<td>"
1334
 
                           . make_my_titlepage()
1335
 
                           . "</td>\n"
1336
 
                           . make_my_titlegraphic()
1337
 
                           . "</tr>\n</table>");
1338
 
        }
1339
 
        else {
1340
 
            $the_title .= ("\n<table border=\"0\" width=\"100%\"><tr>\n"
1341
 
                           . make_my_titlegraphic()
1342
 
                           . "<td>"
1343
 
                           . make_my_titlepage()
1344
 
                           . "</td></tr>\n</table>");
1345
 
        }
1346
 
    }
1347
 
    else {
1348
 
        $the_title .= ("\n<center>"
1349
 
                       . make_my_titlepage()
1350
 
                       . "\n</center>");
1351
 
    }
1352
 
    $the_title .= "\n</div>";
1353
 
    return $the_title . $_;
1354
 
    $the_title .= "\n</center></div>";
1355
 
    return $the_title . $_ ;
1356
 
}
1357
 
 
1358
 
 
1359
 
#
1360
 
#  Module synopsis support
1361
 
#
1362
 
 
1363
 
require SynopsisTable;
1364
 
 
1365
 
sub get_chapter_id(){
1366
 
    my $id = do_cmd_thechapter('');
1367
 
    $id =~ s/<SPAN CLASS="arabic">(\d+)<\/SPAN>/\1/;
1368
 
    $id =~ s/\.//;
1369
 
    return $id;
1370
 
}
1371
 
 
1372
 
# 'chapter' => 'SynopsisTable instance'
1373
 
%ModuleSynopses = ();
1374
 
 
1375
 
sub get_synopsis_table($){
1376
 
    my($chap) = @_;
1377
 
    my $key;
1378
 
    foreach $key (keys %ModuleSynopses) {
1379
 
        if ($key eq $chap) {
1380
 
            return $ModuleSynopses{$chap};
1381
 
        }
1382
 
    }
1383
 
    my $st = SynopsisTable->new();
1384
 
    $ModuleSynopses{$chap} = $st;
1385
 
    return $st;
1386
 
}
1387
 
 
1388
 
sub do_cmd_moduleauthor{
1389
 
    local($_) = @_;
1390
 
    next_argument();
1391
 
    next_argument();
1392
 
    return $_;
1393
 
}
1394
 
 
1395
 
sub do_cmd_sectionauthor{
1396
 
    local($_) = @_;
1397
 
    next_argument();
1398
 
    next_argument();
1399
 
    return $_;
1400
 
}
1401
 
 
1402
 
sub do_cmd_declaremodule{
1403
 
    local($_) = @_;
1404
 
    my $key = next_optional_argument();
1405
 
    my $type = next_argument();
1406
 
    my $name = next_argument();
1407
 
    my $st = get_synopsis_table(get_chapter_id());
1408
 
    #
1409
 
    $key = $name unless $key;
1410
 
    $type = 'built-in' if $type eq 'builtin';
1411
 
    $st->declare($name, $key, $type);
1412
 
    define_module($type, $name);
1413
 
    return anchor_label("module-$key",$CURRENT_FILE,$_)
1414
 
}
1415
 
 
1416
 
sub do_cmd_modulesynopsis{
1417
 
    local($_) = @_;
1418
 
    my $st = get_synopsis_table(get_chapter_id());
1419
 
    $st->set_synopsis($THIS_MODULE, translate_commands(next_argument()));
1420
 
    return $_;
1421
 
}
1422
 
 
1423
 
sub do_cmd_localmoduletable{
1424
 
    local($_) = @_;
1425
 
    my $chap = get_chapter_id();
1426
 
    my $st = get_synopsis_table($chap);
1427
 
    $st->set_file("$CURRENT_FILE");
1428
 
    return "<tex2html-localmoduletable><$chap>\\tableofchildlinks[off]" . $_;
1429
 
}
1430
 
 
1431
 
sub process_all_localmoduletables{
1432
 
    my $key;
1433
 
    my $st, $file;
1434
 
    foreach $key (keys %ModuleSynopses) {
1435
 
        $st = $ModuleSynopses{$key};
1436
 
        $file = $st->get_file();
1437
 
        if ($file) {
1438
 
            process_localmoduletables_in_file($file);
1439
 
        }
1440
 
        else {
1441
 
            print "\nsynopsis table $key has no file association";
1442
 
        }
1443
 
    }
1444
 
}
1445
 
 
1446
 
sub process_localmoduletables_in_file{
1447
 
    my $file = @_[0];
1448
 
    open(MYFILE, "<$file");
1449
 
    local($_);
1450
 
    sysread(MYFILE, $_, 1024*1024);
1451
 
    close(MYFILE);
1452
 
    # need to get contents of file in $_
1453
 
    while (/<tex2html-localmoduletable><(\d+)>/) {
1454
 
        my $match = $&;
1455
 
        my $chap = $1;
1456
 
        my $st = get_synopsis_table($chap);
1457
 
        my $data = $st->tohtml();
1458
 
        s/$match/$data/;
1459
 
    }
1460
 
    open(MYFILE,">$file");
1461
 
    print MYFILE $_;
1462
 
    close(MYFILE);
1463
 
}
1464
 
sub process_python_state{
1465
 
    process_all_localmoduletables();
1466
 
}
1467
 
 
1468
 
 
1469
 
#
1470
 
#  "See also:" -- references placed at the end of a \section
1471
 
#
1472
 
 
1473
 
sub do_env_seealso{
1474
 
    return "<div class='seealso'>\n  "
1475
 
      . "<p class='heading'><b>See Also:</b></p>\n"
1476
 
      . @_[0]
1477
 
      . '</div>';
1478
 
}
1479
 
 
1480
 
sub do_cmd_seemodule{
1481
 
    # Insert the right magic to jump to the module definition.  This should
1482
 
    # work most of the time, at least for repeat builds....
1483
 
    local($_) = @_;
1484
 
    my $key = next_optional_argument();
1485
 
    my $module = next_argument();
1486
 
    my $text = next_argument();
1487
 
    my $period = '.';
1488
 
    $key = $module
1489
 
        unless $key;
1490
 
    if ($text =~ /\.$/) {
1491
 
        $period = '';
1492
 
    }
1493
 
    return '<dl compact class="seemodule">'
1494
 
      . "\n    <dt>Module <b><tt class='module'><a href='module-$key.html'>"
1495
 
      . "$module</a></tt>:</b>"
1496
 
      . "\n    <dd>$text$period\n  </dl>"
1497
 
      . $_;
1498
 
}
1499
 
 
1500
 
sub strip_html_markup($){
1501
 
    my $str = @_[0];
1502
 
    my $s = "$str";
1503
 
    $s =~ s/<[a-zA-Z0-9]+(\s+[a-zA-Z0-9]+(\s*=\s*(\'[^\']*\'|\"[^\"]*\"|[a-zA-Z0-9]+))?)*\s*>//g;
1504
 
    $s =~ s/<\/[a-zA-Z0-9]+>//g;
1505
 
    return $s;
1506
 
}
1507
 
 
1508
 
sub handle_rfclike_reference{
1509
 
    local($_, $what, $format) = @_;
1510
 
    my $rfcnum = next_argument();
1511
 
    my $title = next_argument();
1512
 
    my $text = next_argument();
1513
 
    my $url = get_rfc_url($rfcnum, $format);
1514
 
    my $icon = get_link_icon($url);
1515
 
    my $attrtitle = strip_html_markup($title);
1516
 
    return '<dl compact class="seerfc">'
1517
 
      . "\n    <dt><a href=\"$url\""
1518
 
      . "\n        title=\"$attrtitle\""
1519
 
      . "\n        >$what $rfcnum, <em>$title</em>$icon</a>"
1520
 
      . "\n    <dd>$text\n  </dl>"
1521
 
      . $_;
1522
 
}
1523
 
 
1524
 
sub do_cmd_seepep{
1525
 
    return handle_rfclike_reference(@_[0], "PEP", $PEP_FORMAT);
1526
 
}
1527
 
 
1528
 
sub do_cmd_seerfc{
1529
 
    return handle_rfclike_reference(@_[0], "RFC", $RFC_FORMAT);
1530
 
}
1531
 
 
1532
 
sub do_cmd_seetitle{
1533
 
    local($_) = @_;
1534
 
    my $url = next_optional_argument();
1535
 
    my $title = next_argument();
1536
 
    my $text = next_argument();
1537
 
    if ($url) {
1538
 
        my $icon = get_link_icon($url);
1539
 
        return '<dl compact class="seetitle">'
1540
 
          . "\n    <dt><em class=\"citetitle\"><a href=\"$url\""
1541
 
          . "\n        >$title$icon</a></em>"
1542
 
          . "\n    <dd>$text\n  </dl>"
1543
 
          . $_;
1544
 
    }
1545
 
    return '<dl compact class="seetitle">'
1546
 
      . "\n    <dt><em class=\"citetitle\""
1547
 
      . "\n        >$title</em>"
1548
 
      . "\n    <dd>$text\n  </dl>"
1549
 
      . $_;
1550
 
}
1551
 
 
1552
 
sub do_cmd_seeurl{
1553
 
    local($_) = @_;
1554
 
    my $url = next_argument();
1555
 
    my $text = next_argument();
1556
 
    my $icon = get_link_icon($url);
1557
 
    return '<dl compact class="seeurl">'
1558
 
      . "\n    <dt><a href=\"$url\""
1559
 
      . "\n        class=\"url\">$url$icon</a>"
1560
 
      . "\n    <dd>$text\n  </dl>"
1561
 
      . $_;
1562
 
}
1563
 
 
1564
 
sub do_cmd_seetext{
1565
 
    local($_) = @_;
1566
 
    my $content = next_argument();
1567
 
    return '<div class="seetext"><p>' . $content . '</div>' . $_;
1568
 
}
1569
 
 
1570
 
 
1571
 
#
1572
 
#  Definition list support.
1573
 
#
1574
 
 
1575
 
sub do_env_definitions{
1576
 
    return "<dl class='definitions'>" . @_[0] . "</dl>\n";
1577
 
}
1578
 
 
1579
 
sub do_cmd_term{
1580
 
    local($_) = @_;
1581
 
    my $term = next_argument();
1582
 
    my($name,$aname,$ahref) = new_link_info();
1583
 
    # could easily add an index entry here...
1584
 
    return "<dt><b>$aname" . $term . "</a></b>\n<dd>" . $_;
1585
 
}
1586
 
 
1587
 
 
1588
 
# I don't recall exactly why this was needed, but it was very much needed.
1589
 
# We'll see if anything breaks when I move the "code" line out -- some
1590
 
# things broke with it in.
1591
 
 
1592
 
#code # {}
1593
 
process_commands_wrap_deferred(<<_RAW_ARG_DEFERRED_CMDS_);
1594
 
declaremodule # [] # {} # {}
1595
 
memberline # [] # {}
1596
 
methodline # [] # {} # {}
1597
 
modulesynopsis # {}
1598
 
platform # {}
1599
 
samp # {}
1600
 
setindexsubitem # {}
1601
 
withsubitem # {} # {}
1602
 
_RAW_ARG_DEFERRED_CMDS_
1603
 
 
1604
 
 
1605
 
$alltt_start = '<dl><dd><pre class="verbatim">';
1606
 
$alltt_end = '</pre></dl>';
1607
 
 
1608
 
sub do_env_alltt {
1609
 
    local ($_) = @_;
1610
 
    local($closures,$reopens,@open_block_tags);
1611
 
 
1612
 
    # get the tag-strings for all open tags
1613
 
    local(@keep_open_tags) = @$open_tags_R;
1614
 
    ($closures,$reopens) = &preserve_open_tags() if (@$open_tags_R);
1615
 
 
1616
 
    # get the tags for text-level tags only
1617
 
    $open_tags_R = [ @keep_open_tags ];
1618
 
    local($local_closures, $local_reopens);
1619
 
    ($local_closures, $local_reopens,@open_block_tags)
1620
 
      = &preserve_open_block_tags
1621
 
        if (@$open_tags_R);
1622
 
 
1623
 
    $open_tags_R = [ @open_block_tags ];
1624
 
 
1625
 
    do {
1626
 
        local($open_tags_R) = [ @open_block_tags ];
1627
 
        local(@save_open_tags) = ();
1628
 
 
1629
 
        local($cnt) = ++$global{'max_id'};
1630
 
        $_ = join('',"$O$cnt$C\\tt$O", ++$global{'max_id'}, $C
1631
 
                , $_ , $O, $global{'max_id'}, "$C$O$cnt$C");
1632
 
 
1633
 
        $_ = &translate_environments($_);
1634
 
        $_ = &translate_commands($_) if (/\\/);
1635
 
 
1636
 
        # preserve space-runs, using &nbsp;
1637
 
        while (s/(\S) ( +)/$1$2;SPMnbsp;/g){};
1638
 
        s/(<BR>) /$1;SPMnbsp;/g;
1639
 
 
1640
 
        $_ = join('', $closures, $alltt_start, $local_reopens
1641
 
                , $_
1642
 
                , &balance_tags() #, $local_closures
1643
 
                , $alltt_end, $reopens);
1644
 
        undef $open_tags_R; undef @save_open_tags;
1645
 
    };
1646
 
    $open_tags_R = [ @keep_open_tags ];
1647
 
    $_;
1648
 
}
1649
 
 
1650
 
 
1651
 
1;                              # This must be the last line