The R Project SVN R

Rev

Rev 31770 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 31770 Rev 34091
1
#! @PERL@
1
#! @PERL@
2
#
2
#
3
# ${R_HOME}/bin/Sd2Rd for converting S documentation to Rd format
3
# ${R_HOME}/bin/Sd2Rd for converting S documentation to Rd format
4
 
4
 
5
# Copyright (C) 1997-2001 The R Core Development Team
5
# Copyright (C) 1997-2001 The R Core Development Team
6
#
6
#
7
# This document is free software; you can redistribute it and/or modify
7
# This document is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 2, or (at your option)
9
# the Free Software Foundation; either version 2, or (at your option)
10
# any later version.
10
# any later version.
11
#
11
#
12
# This program is distributed in the hope that it will be useful, but
12
# This program is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
# General Public License for more details.
15
# General Public License for more details.
16
#
16
#
17
# A copy of the GNU General Public License is available via WWW at
17
# A copy of the GNU General Public License is available via WWW at
18
# http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
18
# http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
19
# writing to the Free Software Foundation, Inc., 59 Temple Place,
19
# writing to the Free Software Foundation, Inc., 59 Temple Place,
20
# Suite 330, Boston, MA  02111-1307  USA.
20
# Suite 330, Boston, MA  02111-1307  USA.
21
 
21
 
22
use Getopt::Long;
22
use Getopt::Long;
23
use R::Utils;
23
use R::Utils;
24
 
24
 
25
my $revision = ' $Revision: 1.21 $ ';
25
my $revision = ' $Revision: 1.21 $ ';
26
my $version;
26
my $version;
27
my $name;
27
my $name;
28
 
28
 
29
$revision =~ / ([\d\.]*) /;
29
$revision =~ / ([\d\.]*) /;
30
$version = $1;
30
$version = $1;
31
($name = $0) =~ s|.*/||;
31
($name = $0) =~ s|.*/||;
32
 
32
 
33
sub usage {
33
sub usage {
34
  print STDERR <<END;
34
  print STDERR <<END;
35
Usage: R CMD Sd2Rd [options] FILE
35
Usage: R CMD Sd2Rd [options] FILE
36
 
36
 
37
Convert S documentation in FILE to R documentation format.
37
Convert S documentation in FILE to R documentation format.
38
 
38
 
39
Options:
39
Options:
40
  -h, --help		print short help message and exit
40
  -h, --help		print short help message and exit
41
  -v, --version		print Sd2Rd version info and exit
41
  -v, --version		print Sd2Rd version info and exit
42
  -n			render examples non-executable by wrapping them
42
  -n			render examples non-executable by wrapping them
43
			into a \\dontrun{} environment
43
			into a \\dontrun{} environment
44
  -x			(S3 docs) interpret all single-quoted names 
44
  -x			(S3 docs) interpret all single-quoted names 
45
                        as code names
45
                        as code names
46
 
46
 
47
Email bug reports to <r-bugs\@r-project.org>.
47
Email bug reports to <r-bugs\@r-project.org>.
48
END
48
END
49
  exit 0; 
49
  exit 0; 
50
}
50
}
51
 
51
 
52
@knownoptions = ("v|version", "h|help", "n", "x");
52
@knownoptions = ("v|version", "h|help", "n", "x");
53
GetOptions(@knownoptions) || &usage();
53
GetOptions(@knownoptions) || &usage();
54
&R_version($name, $version) if $opt_v;
54
&R_version($name, $version) if $opt_v;
55
&usage() if $opt_h;
55
&usage() if $opt_h;
56
 
56
 
57
@lines = <>;
57
@lines = <>;
58
## peek at the first line of the file, then dispatch to
58
## peek at the first line of the file, then dispatch to
59
## S3-style (nroff) or S4-style (SGML spec).
59
## S3-style (nroff) or S4-style (SGML spec).
60
if(@lines[0] =~ /^<!doctype/) { doS4(); } else { doS3(); }
60
if(@lines[0] =~ /^<!doctype/) { doS4(); } else { doS3(); }
61
exit 0;
61
exit 0;
62
 
62
 
63
sub doS3 {
63
sub doS3 {
64
  $braceLevel = 0;
64
  $braceLevel = 0;
65
  $inReferences = 0;
65
  $inReferences = 0;
66
  $inVerbatim = 0;
66
  $inVerbatim = 0;
67
  $inSeeAlso = 0;
67
  $inSeeAlso = 0;
68
  $inCode = 0;
68
  $inCode = 0;
69
  $isDataSet = 0;
69
  $isDataSet = 0;
70
  $doprint = 1;
70
  $doprint = 1;
71
  $needArg = 1;
71
  $needArg = 1;
72
  $needVal = 0;
72
  $needVal = 0;
73
  $underlineNext = 0;
73
  $underlineNext = 0;
74
  $output = "";
74
  $output = "";
75
 
75
 
76
  foreach $_ (@lines) {
76
  foreach $_ (@lines) {
77
    chop;
77
    chop;
78
    &substitute unless /^\./;
78
    &substitute unless /^\./;
79
    my @word = split;
79
    my @word = split;
80
 
80
 
81
    if (/^\s*$/) { &output("\n"); }
81
    if (/^\s*$/) { &output("\n"); }
82
    if (/^[^.]/) { 
82
    if (/^[^.]/) { 
83
      if ($underlineNext) {
83
      if ($underlineNext) {
84
	$_ = "\\emph{" . $_ ."}";
84
	$_ = "\\emph{" . $_ ."}";
85
	$underlineNext = 0;
85
	$underlineNext = 0;
86
      }
86
      }
87
      &output($_);
87
      &output($_);
88
    }
88
    }
89
 
89
 
90
    ## Added by BDR 1998-08-27
90
    ## Added by BDR 1998-08-27
91
    if (/^\.\\\"/o) {
91
    if (/^\.\\\"/o) {
92
      s/^\.\\\"/%/;
92
      s/^\.\\\"/%/;
93
      &output($_);
93
      &output($_);
94
    }
94
    }
95
    ## End
95
    ## End
96
 
96
 
97
    if (/^\.BG D/) {
97
    if (/^\.BG D/) {
98
      $isDataSet = 1;
98
      $isDataSet = 1;
99
    }
99
    }
100
    if (/^\.AG/) {
100
    if (/^\.AG/) {
101
      if ($isDataSet) {
101
      if ($isDataSet) {
102
	if ($needArg) {
102
	if ($needArg) {
103
	  &section(1, "\\describe\{");
103
	  &section(1, "\\describe\{");
104
	  $needArg = 0;
104
	  $needArg = 0;
105
	}
105
	}
106
	$arg = $_;
106
	$arg = $_;
107
	$arg =~ s/^\.AG\s//;
107
	$arg =~ s/^\.AG\s//;
108
	&section(2, "\\item\{\\code\{$arg\}\}\{");
108
	&section(2, "\\item\{\\code\{$arg\}\}\{");
109
      } else {
109
      } else {
110
	if ($needArg) {
110
	if ($needArg) {
111
	  &section(0, "\\arguments\{");
111
	  &section(0, "\\arguments\{");
112
	  $needArg = 0;
112
	  $needArg = 0;
113
	}
113
	}
114
	$arg = $_;
114
	$arg = $_;
115
	$arg =~ s/^\.AG\s//;
115
	$arg =~ s/^\.AG\s//;
116
	&section(1, "\\item\{$arg\}\{");
116
	&section(1, "\\item\{$arg\}\{");
117
      }
117
      }
118
    }
118
    }
119
    if (/^\.CS/) {
119
    if (/^\.CS/) {
120
      &section(0, "\\usage\{");
120
      &section(0, "\\usage\{");
121
      $inVerbatim = 1;
121
      $inVerbatim = 1;
122
    }
122
    }
123
    if (/^\.DN/) { &section(0, "\\description\{"); }
123
    if (/^\.DN/) { &section(0, "\\description\{"); }
124
    if (/^\.DT/) { &section(0, "\\details\{"); }
124
    if (/^\.DT/) { &section(0, "\\details\{"); }
125
    if (/^\.EX/) {
125
    if (/^\.EX/) {
126
      if ($opt_n) {
126
      if ($opt_n) {
127
	&section(1, "\\examples\{\\dontrun\{");
127
	&section(1, "\\examples\{\\dontrun\{");
128
      } else {
128
      } else {
129
	&section(0, "\\examples\{");
129
	&section(0, "\\examples\{");
130
      }
130
      }
131
      $inVerbatim = 1;
131
      $inVerbatim = 1;
132
    }
132
    }
133
    if (/^\.FN/) {
133
    if (/^\.FN/) {
134
      unless($fun) { $fun = $word[1]; }
134
      unless($fun) { $fun = $word[1]; }
135
      push(@aliases, $word[1]);
135
      push(@aliases, $word[1]);
136
    }
136
    }
137
    if (/^\.(IP|PP)/) { &output("\n"); }
137
    if (/^\.(IP|PP)/) { &output("\n"); }
138
    if (/^\.KW/) { 
138
    if (/^\.KW/) { 
139
      if ($braceLevel > 0) {
139
      if ($braceLevel > 0) {
140
	&section(0, "");
140
	&section(0, "");
141
	$braceLevel = 0;
141
	$braceLevel = 0;
142
      }
142
      }
143
      if ($word[1] =~ /sysdata/) {
143
      if ($word[1] =~ /sysdata/) {
144
	&output("\\keyword\{datasets\}");
144
	&output("\\keyword\{datasets\}");
145
      } else {
145
      } else {
146
	&output("\\keyword\{$word[1]\}");
146
	&output("\\keyword\{$word[1]\}");
147
      }
147
      }
148
    }
148
    }
149
    if (/^\.RC/) {
149
    if (/^\.RC/) {
150
      if ($needVal) {
150
      if ($needVal) {
151
	$needVal = 0;	    
151
	$needVal = 0;	    
152
	&section(0, "\\value\{\n$output\n");
152
	&section(0, "\\value\{\n$output\n");
153
	$doprint = 1;
153
	$doprint = 1;
154
      }
154
      }
155
      &section(1, "\\item\{" . join(" ", @word[1..$#word]) . "\}\{");
155
      &section(1, "\\item\{" . join(" ", @word[1..$#word]) . "\}\{");
156
    }
156
    }
157
    if (/^\.RT/) {
157
    if (/^\.RT/) {
158
      $needVal = 1;
158
      $needVal = 1;
159
      $doprint = 0;
159
      $doprint = 0;
160
      $output = "";
160
      $output = "";
161
    }
161
    }
162
    if (/^\.SA/) {
162
    if (/^\.SA/) {
163
      &section(0, "\\seealso\{");
163
      &section(0, "\\seealso\{");
164
      $inSeeAlso = 1;
164
      $inSeeAlso = 1;
165
    }
165
    }
166
    if (/^\.SE/) { &section(0, "\\section\{Side Effects\}\{"); }
166
    if (/^\.SE/) { &section(0, "\\section\{Side Effects\}\{"); }
167
    if (/^\.SH/) {
167
    if (/^\.SH/) {
168
      if ($word[1] =~ /REFERENCE/) {
168
      if ($word[1] =~ /REFERENCE/) {
169
	&section(0, "\\references\{");
169
	&section(0, "\\references\{");
170
	$inReferences = 1;
170
	$inReferences = 1;
171
      } elsif ($word[1] =~ /AUTHOR/) {
171
      } elsif ($word[1] =~ /AUTHOR/) {
172
	&section(0, "\\author\{");
172
	&section(0, "\\author\{");
173
      } elsif ($word[1] =~ /NOTE/) {
173
      } elsif ($word[1] =~ /NOTE/) {
174
	&section(0, "\\note\{");
174
	&section(0, "\\note\{");
175
      } elsif ($word[1] =~ /SOURCE/) {
175
      } elsif ($word[1] =~ /SOURCE/) {
176
	&section(0, "\\source\{");
176
	&section(0, "\\source\{");
177
	$inReferences = 1;
177
	$inReferences = 1;
178
      } elsif ($word[1] =~ /SUMMARY/) {
178
      } elsif ($word[1] =~ /SUMMARY/) {
179
	&section(0, "\\description\{");
179
	&section(0, "\\description\{");
180
      } elsif ($word[1] =~ /WARNINGS/) {
180
      } elsif ($word[1] =~ /WARNINGS/) {
181
	&section(0, "\\section{Warnings}\{");
181
	&section(0, "\\section{Warnings}\{");
182
      } elsif ($word[1] =~ /WARNING/) {
182
      } elsif ($word[1] =~ /WARNING/) {
183
	&section(0, "\\section{Warning}\{");
183
	&section(0, "\\section{Warning}\{");
184
      } elsif (join(" ", @word[1..2]) =~ /DATA DESCRIPTION/) {
184
      } elsif (join(" ", @word[1..2]) =~ /DATA DESCRIPTION/) {
185
	&section(0, "\\usage\{\ndata($fun)");
185
	&section(0, "\\usage\{\ndata($fun)");
186
	&section(0, "\\format\{");
186
	&section(0, "\\format\{");
187
      } else {
187
      } else {
188
	# This line may be of the form .SH "A B C"
188
	# This line may be of the form .SH "A B C"
189
	($tmp = join(" ", @word[1..$#word])) =~ s/\"(.*)\"/$1/;
189
	($tmp = join(" ", @word[1..$#word])) =~ s/\"(.*)\"/$1/;
190
	&section(0, "\\section\{$tmp\}\{");
190
	&section(0, "\\section\{$tmp\}\{");
191
      }
191
      }
192
    }
192
    }
193
    if (/^\.sp/) {
193
    if (/^\.sp/) {
194
      if($word[1] == 0) {
194
      if($word[1] == 0) {
195
	output("\\cr")
195
	output("\\cr")
196
      } else {
196
      } else {
197
	output("\n")
197
	output("\n")
198
      }
198
      }
199
    }
199
    }
200
    if (/^\.TL/) {
200
    if (/^\.TL/) {
201
      print("\\name\{$fun\}\n");
201
      print("\\name\{$fun\}\n");
202
      print("\\alias\{", join("\}\n\\alias\{", @aliases), "\}\n");
202
      print("\\alias\{", join("\}\n\\alias\{", @aliases), "\}\n");
203
      &section(0, "\\title\{");
203
      &section(0, "\\title\{");
204
      $inVerbatim = 1;
204
      $inVerbatim = 1;
205
    }
205
    }
206
    if (/^\.WR/) {
206
    if (/^\.WR/) {
207
      &section(0, "");
207
      &section(0, "");
208
      print("% Converted by $name version $version.\n");
208
      print("% Converted by $name version $version.\n");
209
    }
209
    }
210
    if (/^\.AO/) {
210
    if (/^\.AO/) {
211
      output("Arguments for function \\code\{$word[1]()\} can also be");
211
      output("Arguments for function \\code\{$word[1]()\} can also be");
212
      output("supplied to this function.");
212
      output("supplied to this function.");
213
    }
213
    }
214
    if (/^\.GE/) {
214
    if (/^\.GE/) {
215
      output("This is a generic function.");
215
      output("This is a generic function.");
216
      output("Functions with names beginning in \\code\{$fun.\} will be");
216
      output("Functions with names beginning in \\code\{$fun.\} will be");
217
      output("methods for this function.");
217
      output("methods for this function.");
218
      output("Classes with methods for this function include:");
218
      output("Classes with methods for this function include:");
219
    }
219
    }
220
    if (/^\.GR/) {
220
    if (/^\.GR/) {
221
      output("Graphical parameters (see \\code\{\\link\{par\}\}) may also");
221
      output("Graphical parameters (see \\code\{\\link\{par\}\}) may also");
222
      output("be supplied as arguments to this function.");
222
      output("be supplied as arguments to this function.");
223
    }
223
    }
224
    if (/^\.ME/) {
224
    if (/^\.ME/) {
225
      output("This function is a method for the generic function");
225
      output("This function is a method for the generic function");
226
      output("\\code\{$word[1]()\} for class \\code\{\"$word[2]\"\}.");
226
      output("\\code\{$word[1]()\} for class \\code\{\"$word[2]\"\}.");
227
      output("It can be invoked by calling \\code\{$word[1](x)\} for an");
227
      output("It can be invoked by calling \\code\{$word[1](x)\} for an");
228
      output("object \\code\{x\} of the appropriate class, or directly by");
228
      output("object \\code\{x\} of the appropriate class, or directly by");
229
      output("calling \\code\{$word[1].$word[2](x)\} regardless of the");
229
      output("calling \\code\{$word[1].$word[2](x)\} regardless of the");
230
      output("class of the object.");
230
      output("class of the object.");
231
    }
231
    }
232
    if (/^\.NA/) { output("Missing values (\\code\{NA\}s) are allowed."); }
232
    if (/^\.NA/) { output("Missing values (\\code\{NA\}s) are allowed."); }
233
    if (/^\.Tl/) {
233
    if (/^\.Tl/) {
234
      output("In addition, the high-level graphics control arguments");
234
      output("In addition, the high-level graphics control arguments");
235
      output("described under \\code\{\\link\{par\}\} and the arguments to");
235
      output("described under \\code\{\\link\{par\}\} and the arguments to");
236
      output("\\code\{\\link\{title\}\} may be supplied to this function.");
236
      output("\\code\{\\link\{title\}\} may be supplied to this function.");
237
    }
237
    }
238
    if (/^\.ul/) { $underlineNext = 1; }
238
    if (/^\.ul/) { $underlineNext = 1; }
239
    ## End
239
    ## End
240
  }
240
  }
241
}
241
}
242
 
242
 
243
sub substitute {
243
sub substitute {
244
  if (!$inVerbatim) {
244
  if (!$inVerbatim) {
245
    s/\{/\\\{/g;
245
    s/\{/\\\{/g;
246
    s/\}/\\\}/g;
246
    s/\}/\\\}/g;
247
#    s/&/\\&/g; removed BDR 2000-02-10
247
#    s/&/\\&/g; removed BDR 2000-02-10
248
    ## Added by BDR 1998-06-20
248
    ## Added by BDR 1998-06-20
249
    s/\\\(aa/'/g;		# extra ' for highlight matching
249
    s/\\\(aa/'/g;		# extra ' for highlight matching
250
    s/\\\(em/--/g;		# em dash
250
    s/\\\(em/--/g;		# em dash
251
    s/\\\(tm/ (TM) /g;		# Trademark
251
    s/\\\(tm/ (TM) /g;		# Trademark
252
    s/\\\(mu/ x /g;		# multiply sign
252
    s/\\\(mu/ x /g;		# multiply sign
253
    s/\\\(\*a/\alpha/g;		# greek
253
    s/\\\(\*a/\alpha/g;		# greek
254
    s/\\\(\*b/\beta/g;
254
    s/\\\(\*b/\beta/g;
255
    s/\\\(\*e/\epsilon/g;
255
    s/\\\(\*e/\epsilon/g;
256
    s/\\\(\*l/\lambda/g;
256
    s/\\\(\*l/\lambda/g;
257
    s/\\\(\*m/\mu/g;
257
    s/\\\(\*m/\mu/g;
258
    s/\\\(\*p/\pi/g;
258
    s/\\\(\*p/\pi/g;
259
    s/\\\(\*s/\sigma/g;
259
    s/\\\(\*s/\sigma/g;
260
    ## End
260
    ## End
261
  }
261
  }
262
  s/\.\.\./\\dots/g;
262
  s/\.\.\./\\dots/g;
263
  s/\\fB/\\bold\{/g;
263
  s/\\fB/\\bold\{/g;
264
  s/\\fR/\}/g;
264
  s/\\fR/\}/g;
265
  ## Added by BDR 1998-06-20
265
  ## Added by BDR 1998-06-20
266
  s/\\fI/\\emph\{/g;
266
  s/\\fI/\\emph\{/g;
267
  s/\\fP/\}/g;
267
  s/\\fP/\}/g;
268
  ## End
268
  ## End
269
  s/\%/\\%/g;
269
  s/\%/\\%/g;
270
  s/\\\.(.*)$/# $1)/g;
270
  s/\\\.(.*)$/# $1)/g;
271
  if($inCode && s/\'/\}/) {
271
  if($inCode && s/\'/\}/) {
272
    $inCode = 0;
272
    $inCode = 0;
273
  }
273
  }
274
  if ($inSeeAlso) {
274
  if ($inSeeAlso) {
275
    if ($opt_x) {
275
    if ($opt_x) {
276
      s/\`?([\.\w]*\w+)\'?/\\code{\\link{$1}}/g;
276
      s/\`?([\.\w]*\w+)\'?/\\code{\\link{$1}}/g;
277
    } else {
277
    } else {
278
      s/\`([^\']*)\'/\\code{\\link{$1}}/g;
278
      s/\`([^\']*)\'/\\code{\\link{$1}}/g;
279
    }
279
    }
280
  } elsif (!$inVerbatim) {
280
  } elsif (!$inVerbatim) {
281
    if(s/\`([^\']*)$/\\code\{$1/) {
281
    if(s/\`([^\']*)$/\\code\{$1/) {
282
      $inCode = 1;
282
      $inCode = 1;
283
    }
283
    }
284
    s/\`([^\']*)\'$/\\code{$1}/g;
284
    s/\`([^\']*)\'$/\\code{$1}/g;
285
    s/\`([^\']*)\'([^\'])/\\code{$1}$2/g;  
285
    s/\`([^\']*)\'([^\'])/\\code{$1}$2/g;  
286
  }
286
  }
287
  if ($inReferences) {
287
  if ($inReferences) {
288
    s/([0-9])-([0-9])/$1--$2/g;
288
    s/([0-9])-([0-9])/$1--$2/g;
289
  }
289
  }
290
}
290
}
291
 
291
 
292
sub section {
292
sub section {
293
  my($level, $text) = @_;
293
  my($level, $text) = @_;
294
  $n = $braceLevel - $level;
294
  $n = $braceLevel - $level;
295
  print "\}" x $n, "\n" if ($n > 0);
295
  print "\}" x $n, "\n" if ($n > 0);
296
  if ($needVal) {
296
  if ($needVal) {
297
    print("\\value\{\n$output\n\}\n");
297
    print("\\value\{\n$output\n\}\n");
298
    $needVal = 0;
298
    $needVal = 0;
299
  }
299
  }
300
  print("$text\n") if $text;    
300
  print("$text\n") if $text;    
301
  $braceLevel = $level + 1;
301
  $braceLevel = $level + 1;
302
  $inReferences = 0;
302
  $inReferences = 0;
303
  $inVerbatim = 0;
303
  $inVerbatim = 0;
304
  $inSeeAlso = 0;
304
  $inSeeAlso = 0;
305
  $doprint = 1;    
305
  $doprint = 1;    
306
}
306
}
307
 
307
 
308
sub paragraph {
308
sub paragraph {
309
  my($name) = @_;
309
  my($name) = @_;
310
  &output("\n\\bold\{$name.\} ");
310
  &output("\n\\bold\{$name.\} ");
311
}
311
}
312
    
312
    
313
sub output {
313
sub output {
314
  my($text) = @_;
314
  my($text) = @_;
315
  if ($doprint) {
315
  if ($doprint) {
316
    print("$text\n");
316
    print("$text\n");
317
  } elsif ($output) {
317
  } elsif ($output) {
318
    $output .= "\n$text";
318
    $output .= "\n$text";
319
  } else {
319
  } else {
320
    $output = $text;
320
    $output = $text;
321
  }
321
  }
322
}
322
}
323
 
323
 
324
 
324
 
325
## ---------------------------- S4 section -------------------------
325
## ---------------------------- S4 section -------------------------
326
 
326
 
327
my $skipping = 0;
327
my $skipping = 0;
328
my $nextskipping = 0;
328
my $nextskipping = 0;
329
my $text = "";
329
my $text = "";
330
my $fun;
330
my $fun;
331
my $InArgs = 0;
331
my $InArgs = 0;
332
 
332
 
-
 
333
my $nalias = 0;
-
 
334
my $nexamples = 0;
-
 
335
 
333
sub doS4 {
336
sub doS4 {
334
  foreach $_ (@lines) {
337
  foreach $_ (@lines) {
335
    # skip header
338
    # skip header
336
    if (/^<!doctype/) {
339
    if (/^<!doctype/) {
337
      $skipping = 1;
340
      $skipping = 1;
338
      $nextskipping = 1 unless />\s*$/s;
341
      $nextskipping = 1 unless />\s*$/s;
339
    }
342
    }
340
    if($skipping && /^>/) { $nextskipping = 0;}
343
    if($skipping && /^>/) { $nextskipping = 0;}
341
    # skip comments
344
    # skip comments
342
    $skipping = $nextskipping = 1 if (/^\s*<\!-- /);
345
    $skipping = $nextskipping = 1 if (/^\s*<\!-- /);
343
    if($skipping && /-->\s*$/) { $nextskipping = 0;}
346
    if($skipping && /-->\s*$/) { $nextskipping = 0;}
344
    if(!$skipping) {
347
    if(!$skipping) {
345
      $text = $text . $_;
348
      $text = $text . $_;
346
    }
349
    }
347
    $skipping = $nextskipping;
350
    $skipping = $nextskipping;
348
  }
351
  }
349
 
352
 
350
  ($type, $text, $rest) = get_group($text); # s-function-doc or whatever
353
  ($type, $text, $rest) = get_group($text); # s-function-doc or whatever
351
  if($type ne "function-doc" && $type ne "method-doc") {
354
  if($type ne "function-doc" && $type ne "method-doc") {
352
    die "Document class `s-$type' is not supported";
355
    die "Document class 's-$type' is not supported";
353
  }
356
  }
354
 
357
 
355
  chomp $text;
358
  chomp $text;
356
 
359
 
357
  while(length($text) > 0) {
360
  while(length($text) > 0) {
358
    ($type, $body, $text) = get_group($text);
361
    ($type, $body, $text) = get_group($text);
359
    process_group($type, $body);
362
    process_group($type, $body);
360
  }
363
  }
361
  print "% Converted by $name version $version.\n";
364
  print "% Converted by $name version $version.\n";
362
  ## End
365
  ## End
363
}
366
}
364
 
367
 
365
sub get_group
368
sub get_group
366
{
369
{
367
    my $text = $_[0];
370
    my $text = $_[0];
368
    my $body;
371
    my $body;
369
    my $rest;
372
    my $rest;
370
 
373
 
371
    die "not at beginning of a group in |$text|" unless 
374
    die "not at beginning of a group in |$text|" unless 
372
	$text =~ /^\s*<s-(.+?)>/s;
375
	$text =~ /^\s*<s-(.+?)>/s;
373
    my $type = $1;
376
    my $type = $1;
374
    my $tt = $type;
377
    my $tt = $type;
375
    $tt =~ s/([a-zA-Z-]+).*/$1/;
378
    $tt =~ s/([a-zA-Z-]+).*/$1/;
376
    if($text =~ /^\s*<s-\Q$type\E>(.*?)<\/s-$tt>(.*)/s) {
379
    if($text =~ /^\s*<s-\Q$type\E>(.*?)<\/s-$tt>(.*)/s) {
377
	$body = $1;
380
	$body = $1;
378
	$rest = $2;
381
	$rest = $2;
379
    } else { 
382
    } else { 
380
	warn "no match for `s-$tt'";
383
	warn "no match for 's-$tt'";
381
	$text =~ /^\s*<s-\Q$type\E>\s*(.*)/s;
384
	$text =~ /^\s*<s-\Q$type\E>\s*(.*)/s;
382
	$body = $1;
385
	$body = $1;
383
	$rest = "";
386
	$rest = "";
384
    }
387
    }
385
    ($type, $body, $rest);
388
    ($type, $body, $rest);
386
}
389
}
387
 
390
 
388
sub process_group {
391
sub process_group {
389
    my $type = $_[0];
392
    my $type = $_[0];
390
    my $text = $_[1];
393
    my $text = $_[1];
391
 
394
 
392
    if($InArgs && ($type =~ /^args/) != 1) {
395
    if($InArgs && ($type =~ /^args/) != 1) {
393
	print "}\n";
396
	print "}\n";
394
	$InArgs = 0;
397
	$InArgs = 0;
395
    }
398
    }
396
 
399
 
397
    $text =~ s/^\n*//;
400
    $text =~ s/^\n*//;
398
    $text =~ s/\n*$//;
401
    $text =~ s/\n*$//;
399
 
402
 
400
    if ($type eq "topics") {
403
    if ($type eq "topics") {
401
	process_sub_groups($text, "topic");
404
	process_sub_groups($text, "topic");
402
 
405
 
403
    } elsif ($type eq "title") {
406
    } elsif ($type eq "title") {
404
	print "\\title{\n  $text\n}\n";
407
	print "\\title{\n  $text\n}\n";
405
 
408
 
406
    } elsif ($type eq "description") {
409
    } elsif ($type eq "description") {
407
	print "\\description{\n", sub4($text), "\n}\n";	
410
	print "\\description{\n", sub4($text), "\n}\n";	
408
 
411
 
409
    } elsif ($type eq "usage") {
412
    } elsif ($type eq "usage") {
410
	## new-style usage is not catered for here: no examples seen
413
	## new-style usage is not catered for here: no examples seen
411
	## it will be passed through verbatim.
414
	## it will be passed through verbatim.
412
	if ($text =~ /^\s*<s-old-style-usage>\s*(.*?)\s*<\/s-old-style-usage>/s) {
415
	if ($text =~ /^\s*<s-old-style-usage>\s*(.*?)\s*<\/s-old-style-usage>/s) {
413
	    $text = $1;
416
	    $text = $1;
414
	}
417
	}
415
	print "\\usage{\n$text\n}\n";	
418
	print "\\usage{\n$text\n}\n";	
416
 
419
 
417
    } elsif ($type eq "args" || $type eq "args-optional" 
420
    } elsif ($type eq "args" || $type eq "args-optional" 
418
	     || $type eq "args-required" ) {
421
	     || $type eq "args-required" ) {
419
	if(!$InArgs) {
422
	if(!$InArgs) {
420
	    print "\\arguments{\n";
423
	    print "\\arguments{\n";
421
	    $InArgs = 1;
424
	    $InArgs = 1;
422
	}
425
	}
423
	## some files seem to have text before args
426
	## some files seem to have text before args
424
	my $pre = $text =~ /^\s*<s-arg/;
427
	my $pre = $text =~ /^\s*<s-arg/;
425
	if($pre != 1) {
428
	if($pre != 1) {
426
	    my $pre;
429
	    my $pre;
427
	    if($text =~ s/^\s*(.*?)(<s-arg)/$2/s) {
430
	    if($text =~ s/^\s*(.*?)(<s-arg)/$2/s) {
428
		$pre = $1;
431
		$pre = $1;
429
	    } else {
432
	    } else {
430
		## There are no <s-arg> groups!
433
		## There are no <s-arg> groups!
431
		$pre = $text;
434
		$pre = $text;
432
		$text = "";
435
		$text = "";
433
	    }
436
	    }
434
	    print sub4($pre), "\n";
437
	    print sub4($pre), "\n";
435
	}
438
	}
436
	process_sub_groups($text, "arg");
439
	process_sub_groups($text, "arg");
437
 
440
 
438
    } elsif ($type eq "value") {
441
    } elsif ($type eq "value") {
439
	print "\\value{\n";
442
	print "\\value{\n";
440
	my $t;
443
	my $t;
441
	my @groups = split /<s-return-component /, $text;
444
	my @groups = split /<s-return-component /, $text;
442
	foreach $t (@groups) {
445
	foreach $t (@groups) {
443
	    if ($t =~ /name=\"(.*?)\">\s*(.*)<\/s-return-component>/s) {
446
	    if ($t =~ /name=\"(.*?)\">\s*(.*)<\/s-return-component>/s) {
444
		my $name=$1;
447
		my $name=$1;
445
		$t = $2;
448
		$t = $2;
446
		print "\\item{$1}{\n", sub4($t), "}\n";
449
		print "\\item{$1}{\n", sub4($t), "}\n";
447
	    } else {
450
	    } else {
448
		print sub4($t), "\n";
451
		print sub4($t), "\n";
449
	    }
452
	    }
450
	}
453
	}
451
	print "}\n";
454
	print "}\n";
452
 
455
 
453
    } elsif ($type eq "details") {
456
    } elsif ($type eq "details") {
454
	print "\\details{\n", sub4($text), "\n}\n";	
457
	print "\\details{\n", sub4($text), "\n}\n";	
455
 
458
 
456
    } elsif ($type eq "see") {
459
    } elsif ($type eq "see") {
457
 	print "\\seealso{\n", makelinks($text), "\n}\n";	
460
 	print "\\seealso{\n", makelinks($text), "\n}\n";	
458
 
461
 
459
    } elsif ($type eq "examples") {
462
    } elsif ($type eq "examples") {
460
	print "\\examples{\n";
463
	print "\\examples{\n";
461
	print "\\dontrun{\n" if $opt_n;
464
	print "\\dontrun{\n" if $opt_n;
462
	process_sub_groups($text, "example");
465
	process_sub_groups($text, "example");
463
	print "}\n" if $opt_n;
466
	print "}\n" if $opt_n;
464
	print "}\n";
467
	print "}\n";
465
 
468
 
466
    } elsif ($type eq "note" || $type eq "notes") {
469
    } elsif ($type eq "note" || $type eq "notes") {
467
	print "\\note{\n", sub4($text), "\n}\n";	
470
	print "\\note{\n", sub4($text), "\n}\n";	
468
 
471
 
469
    } elsif ($type eq "bugs") {
472
    } elsif ($type eq "bugs") {
470
 	print "\\section{Bugs}{\n", sub4($text), "\n}\n";	
473
 	print "\\section{Bugs}{\n", sub4($text), "\n}\n";	
471
 
474
 
472
    } elsif ($type eq "references") {
475
    } elsif ($type eq "references") {
473
	print "\\references{\n", inref(sub4($text)), "\n}\n";	
476
	print "\\references{\n", inref(sub4($text)), "\n}\n";	
474
 
477
 
475
    } elsif ($type =~ /^section\s+name\s*=\s*(.*)/) {
478
    } elsif ($type =~ /^section\s+name\s*=\s*(.*)/) {
476
	my $name = $1;
479
	my $name = $1;
477
	$name =~ s/\s*\"(.*?)\"/$1/o;
480
	$name =~ s/\s*\"(.*?)\"/$1/o;
478
	$name =~ s/^\s*//o;
481
	$name =~ s/^\s*//o;
479
	if ($name =~ /^reference$/io) {
482
	if ($name =~ /^reference$/io) {
480
	    print "\\references{\n", inref(sub4($text)), "\n}\n";	
483
	    print "\\references{\n", inref(sub4($text)), "\n}\n";	
481
	} elsif ($name =~ /^source$/io) {
484
	} elsif ($name =~ /^source$/io) {
482
	    print "\\source{\n", inref(sub4($text)), "\n}\n";	
485
	    print "\\source{\n", inref(sub4($text)), "\n}\n";	
483
	} elsif ($name =~ /^note$/io) {
486
	} elsif ($name =~ /^note$/io) {
484
	    print "\\note{\n", sub4($text), "\n}\n";	
487
	    print "\\note{\n", sub4($text), "\n}\n";	
485
	} elsif ($name =~ /^summary$/io) {
488
	} elsif ($name =~ /^summary$/io) {
486
	    print "\\description{\n", sub4($text), "\n}\n";	
489
	    print "\\description{\n", sub4($text), "\n}\n";	
487
	} elsif ($name =~ /^data description$/io) {
490
	} elsif ($name =~ /^data description$/io) {
488
	    print "\\usage{\ndata($fun)\n}\n";
491
	    print "\\usage{\ndata($fun)\n}\n";
489
	    print "\\format{\n", sub4($text), "\n}\n";	
492
	    print "\\format{\n", sub4($text), "\n}\n";	
490
	} else {
493
	} else {
491
	    $name = lc($name);
494
	    $name = lc($name);
492
	    $name =~ s/^([a-z])/\U$1/;
495
	    $name =~ s/^([a-z])/\U$1/;
493
	    print "\\section{$name}{\n", sub4($text), "\n}\n";	
496
	    print "\\section{$name}{\n", sub4($text), "\n}\n";	
494
	}
497
	}
495
 
498
 
496
    } elsif ($type eq "docclass") {
499
    } elsif ($type eq "docclass") {
497
	print "% docclass is $text\n";
500
	print "% docclass is $text\n";
498
 
501
 
499
    } elsif ($type eq "warnings") {
502
    } elsif ($type eq "warnings") {
500
	process_sub_groups($text, "warning");
503
	process_sub_groups($text, "warning");
501
 
504
 
502
    } elsif ($type eq "warning") {
505
    } elsif ($type eq "warning") {
503
	print "\\section{Warning}{\n", sub4($text), "\n}\n";	
506
	print "\\section{Warning}{\n", sub4($text), "\n}\n";	
504
 
507
 
505
    } elsif ($type eq "background") {
508
    } elsif ($type eq "background") {
506
	print "\\section{Background}{\n", sub4($text), "\n}\n";	
509
	print "\\section{Background}{\n", sub4($text), "\n}\n";	
507
 
510
 
508
    } elsif ($type eq "side-effects") {
511
    } elsif ($type eq "side-effects") {
509
	print "\\section{Side Effects}{\n", sub4($text), "\n}\n";	
512
	print "\\section{Side Effects}{\n", sub4($text), "\n}\n";	
510
 
513
 
511
    } elsif ($type eq "author") {
514
    } elsif ($type eq "author") {
512
	print "\\author{\n", sub4($text), "\n}\n";	
515
	print "\\author{\n", sub4($text), "\n}\n";	
513
 
516
 
514
    } elsif ($type eq "keywords") {
517
    } elsif ($type eq "keywords") {
515
	process_sub_groups($text, "keyword");
518
	process_sub_groups($text, "keyword");
516
 
519
 
517
    } else {
520
    } else {
518
	warn "unknown SGML entity `$type'";
521
	warn "unknown SGML entity '$type'";
519
	print "%type:\n%$text\n";
522
	print "%type:\n%$text\n";
520
    }
523
    }
521
}
524
}
522
 
525
 
523
sub process_sub_groups{
526
sub process_sub_groups {
-
 
527
  
524
    my $text = $_[0];
528
    my $text = $_[0];
525
    my $topic = $_[1];
529
    my $topic = $_[1];
526
 
530
 
527
    while(length($text) > 0) {
531
    while(length($text) > 0) {
528
	($type, $body, $text) = get_group($text);
532
	($type, $body, $text) = get_group($text);
529
	die "invalid subgroup" unless $type =~ /^$topic/;
533
	die "invalid subgroup" unless $type =~ /^$topic/;
530
	process_sub_group($type, $body);
534
	process_sub_group($type, $body);
531
    }
535
    }
532
}
536
}
533
 
537
 
534
sub process_sub_group{
538
sub process_sub_group {
-
 
539
  
535
    my $topic = $_[0];
540
    my $topic = $_[0];
536
    my $text = $_[1];
541
    my $text = $_[1];
537
    my $nalias = 0;
-
 
538
    my $example = 0;
-
 
539
 
542
 
540
    $text =~ s/^\n*//;
543
    $text =~ s/^\n*//;
541
    $text =~ s/\n*$//;
544
    $text =~ s/\n*$//;
542
    if ($type eq "topic") {
545
    if ($type eq "topic") {
543
	 $text =~ s/^\s*//; $text =~ s/\s*$//;
546
	 $text =~ s/^\s*//; $text =~ s/\s*$//;
544
	if(!$nalias) {
547
	if(!$nalias) {
545
	    print "\\name{$text}\n";
548
	    print "\\name{$text}\n";
546
	    $nalias = 1;
549
	    $nalias = 1;
547
	    $fun = $text;
550
	    $fun = $text;
548
	}
551
	}
549
	print "\\alias{$text}\n";
552
	print "\\alias{$text}\n";
550
    } elsif ($type eq "warning") {
553
    } elsif ($type eq "warning") {
551
	print "\\section{Warning}{\n", sub4($text), "\n}\n";	
554
	print "\\section{Warning}{\n", sub4($text), "\n}\n";	
552
    } elsif ($type eq "keyword") {
555
    } elsif ($type eq "keyword") {
553
	print "\\keyword{$text}\n";
556
	print "\\keyword{$text}\n";
554
    } elsif ($type =~ /^example/) {
557
    } elsif ($type =~ /^example/) {
555
	if ($nexample++ > 0) { print "\n"; }
558
	if ($nexample++ > 0) { print "\n"; }
556
	print verbsub($text), "\n";
559
	print verbsub($text), "\n";
557
    } elsif ($type =~ /^arg/) {
560
    } elsif ($type =~ /^arg/) {
558
	$type =~ /^arg\s+name\s*=\s*(.*)/;
561
	$type =~ /^arg\s+name\s*=\s*(.*)/;
559
	my $name = $1;
562
	my $name = $1;
560
	$name =~ s/\s*\"(.*?)\"/$1/o;
563
	$name =~ s/\s*\"(.*?)\"/$1/o;
561
	$name =~ s/\s*(\w*)\s*/$1/o;
564
	$name =~ s/\s*(\w*)\s*/$1/o;
562
	$name =~ s/\.\.\./\\dots/;
565
	$name =~ s/\.\.\./\\dots/;
563
	print "\\item{$name}{\n", sub4($text), "\n}\n";	
566
	print "\\item{$name}{\n", sub4($text), "\n}\n";	
564
    } else {
567
    } else {
565
	warn "unknown SGML entity `$type'";
568
	warn "unknown SGML entity '$type'";
566
	print "%type:\n%$text\n";
569
	print "%type:\n%$text\n";
567
    }
570
    }
568
}
571
}
569
 
572
 
570
sub inref {
573
sub inref {
571
    my $text = $_[0];
574
    my $text = $_[0];
572
    $text =~ s/([0-9])-([0-9])/$1--$2/go;
575
    $text =~ s/([0-9])-([0-9])/$1--$2/go;
573
    $text;
576
    $text;
574
}
577
}
575
 
578
 
576
sub verbsub {
579
sub verbsub {
577
    my $text = $_[0];
580
    my $text = $_[0];
578
    $text =~ s/&gt;/>/go;
581
    $text =~ s/&gt;/>/go;
579
    $text =~ s/&lt;/</go;
582
    $text =~ s/&lt;/</go;
580
    $text =~ s/&#38;/&/go;
583
    $text =~ s/&#38;/&/go;
581
    $text =~ s/\%/\\%/go;
584
    $text =~ s/\%/\\%/go;
582
    $text;
585
    $text;
583
}
586
}
584
 
587
 
585
sub sub4 {
588
sub sub4 {
586
    my $text = $_[0];
589
    my $text = $_[0];
587
    $text =~ s/\{/\\\{/go;
590
    $text =~ s/\{/\\\{/go;
588
    $text =~ s/\}/\\\}/go;
591
    $text =~ s/\}/\\\}/go;
589
 
592
 
590
    ## These tags can have id's
593
    ## These tags can have id's
591
    $text =~ s+<s-expression(.*?)>(.*?)</s-expression>+\\code{$2}+go;
594
    $text =~ s+<s-expression(.*?)>(.*?)</s-expression>+\\code{$2}+go;
592
    $text =~ s+<s-object(.*?)>(.*?)</s-object>+\\code{$2}+go;
595
    $text =~ s+<s-object(.*?)>(.*?)</s-object>+\\code{$2}+go;
593
    $text =~ s+<s-function(.*?)>(.*?)</s-function>+\\code{$2}+go;
596
    $text =~ s+<s-function(.*?)>(.*?)</s-function>+\\code{$2}+go;
594
    $text =~ s+<s-class(.*?)>(.*?)</s-class>+\\code{$2}+go;
597
    $text =~ s+<s-class(.*?)>(.*?)</s-class>+\\code{$2}+go;
595
    $text =~ s+<s-method(.*?)>(.*?)</s-method>+\\code{$2}+go;
598
    $text =~ s+<s-method(.*?)>(.*?)</s-method>+\\code{$2}+go;
596
    $text =~ s+<s-dataset(.*?)>(.*?)</s-dataset>+\\code{$2}+go;
599
    $text =~ s+<s-dataset(.*?)>(.*?)</s-dataset>+\\code{$2}+go;
597
    ## I have never seen these used
600
    ## I have never seen these used
598
    $text =~ s+<s-expref(.*?)>(.*?)</s-expref>+\\code{$2}+go;
601
    $text =~ s+<s-expref(.*?)>(.*?)</s-expref>+\\code{$2}+go;
599
    $text =~ s+<s-objref(.*?)>(.*?)</s-objref>+\\code{$2}+go;
602
    $text =~ s+<s-objref(.*?)>(.*?)</s-objref>+\\code{$2}+go;
600
    $text =~ s+<s-function-ref(.*?)>(.*?)</s-function-ref>+\\code{$2}+go;
603
    $text =~ s+<s-function-ref(.*?)>(.*?)</s-function-ref>+\\code{$2}+go;
601
    $text =~ s+<s-clsref(.*?)>(.*?)</s-clsref>+\\code{$2}+go;
604
    $text =~ s+<s-clsref(.*?)>(.*?)</s-clsref>+\\code{$2}+go;
602
    $text =~ s+<s-mthref(.*?)>(.*?)</s-mthref>+\\code{$2}+go;
605
    $text =~ s+<s-mthref(.*?)>(.*?)</s-mthref>+\\code{$2}+go;
603
    $text =~ s+<s-datref(.*?)>(.*?)</s-datref>+\\code{$2}+go;
606
    $text =~ s+<s-datref(.*?)>(.*?)</s-datref>+\\code{$2}+go;
604
    $text =~ s+<s-chpref(.*?)>(.*?)</s-chpref>+\\code{$2}+go;
607
    $text =~ s+<s-chpref(.*?)>(.*?)</s-chpref>+\\code{$2}+go;
605
 
608
 
606
    $text =~ s+<it>(.*?)</it>+\\emph{$1}+go;
609
    $text =~ s+<it>(.*?)</it>+\\emph{$1}+go;
607
    $text =~ s+<sl>(.*?)</sl>+\\emph{$1}+go;
610
    $text =~ s+<sl>(.*?)</sl>+\\emph{$1}+go;
608
    $text =~ s+<em>(.*?)</em>+\\emph{$1}+go;
611
    $text =~ s+<em>(.*?)</em>+\\emph{$1}+go;
609
    # not clear what to do with <sf>
612
    # not clear what to do with <sf>
610
    $text =~ s+<sf>(.*?)</sf>+\\bold{$1}+go;
613
    $text =~ s+<sf>(.*?)</sf>+\\bold{$1}+go;
611
    $text =~ s+<bf>(.*?)</bf>+\\bold{$1}+go;
614
    $text =~ s+<bf>(.*?)</bf>+\\bold{$1}+go;
612
    $text =~ s+<tt>(.*?)</tt>+\\code{$1}+go;
615
    $text =~ s+<tt>(.*?)</tt>+\\code{$1}+go;
613
    $text =~ s+<url>(.*?)</url>+\\url{$1}+go;
616
    $text =~ s+<url>(.*?)</url>+\\url{$1}+go;
614
    $text =~ s/\n*<p>\n*/\n\n/go;
617
    $text =~ s/\n*<p>\n*/\n\n/go;
615
    $text =~ s/(<br>\n*)+/\n/go;
618
    $text =~ s/(<br>\n*)+/\n/go;
616
    $text =~ s/\$/\\\$/go;
619
    $text =~ s/\$/\\\$/go;
617
    $text =~ s/@/\\@/go;
620
    $text =~ s/@/\\@/go;
618
 
621
 
619
    verbsub($text);
622
    verbsub($text);
620
}
623
}
621
 
624
 
622
sub makelinks {
625
sub makelinks {
623
    my $text = $_[0];
626
    my $text = $_[0];
624
 
627
 
625
    $text =~ s+<s-function name="(.*?)">(.*?)</s-function>+\\code{\\link{$2}}+go;
628
    $text =~ s+<s-function name="(.*?)">(.*?)</s-function>+\\code{\\link{$2}}+go;
626
    $text;
629
    $text;
627
}
630
}
628
 
631
 
629
 
632
 
630
### Local Variables: ***
633
### Local Variables: ***
631
### mode: perl ***
634
### mode: perl ***
632
### perl-indent-level: 2 ***
635
### perl-indent-level: 2 ***
633
### End: ***
636
### End: ***