1#!/usr/local/bin/perl
2#
3# Copyright (c) 2001 Tama Communications Corporation
4#
5# This file is part of GNU GLOBAL.
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20# Main procedure.
21#
22$com = $0;
23$com =~ s/.*\///;
24while ($ARGV[0] =~ /^-/) {
25        $opt = shift;
26        if ($opt eq '--c') {
27                $c = 1;
28        } elsif ($opt eq '--perl') {
29                $perl = 1;
30        } elsif ($opt eq '--man') {
31                $man = 1;
32	} elsif ($opt eq '--info') {
33                $info = 1;
34	} elsif ($opt eq '--menu') {
35                $menu = 1;
36	}
37}
38if ($menu) {
39	&menu'gen(@ARGV);
40} else {
41	$infile = $ARGV[0];
42	open(INFILE, $infile) || die("cannot open '$infile'\n");
43	if ($c) {
44		&c'gen();
45	} elsif ($perl) {
46		&perl'gen();
47	} elsif ($man) {
48		&man'gen();
49	} elsif ($info) {
50		&info'gen();
51	}
52	close(INFILE);
53}
54exit 0;
55#------------------------------------------------------------------
56#
57# Generate langmap statement.
58#
59#------------------------------------------------------------------
60#
61# Get a value from configure.ac file by name.
62#
63sub getvalue {
64	my($name) = @_;
65	my $value;
66	#
67	# A value should be defined as:
68	# NAME='VALUE'
69	#
70	my $line=`grep "$name=" configure.ac`;
71	($value) = $line =~ /^$name='(.*)'$/;
72	unless ($value) {
73		print STDERR "$name not found.\n";
74		exit(1);
75	}
76	$value;
77}
78#
79# Generate statements about the langmap variable.
80#
81sub langmapstatement {
82	my($maps) = getvalue('DEFAULTLANGMAP');
83	my(@statement);
84	my %name = (
85		'c'	=> 'C',
86		'yacc'	=> 'Yacc',
87		'java'	=> 'Java',
88		'cpp'	=> 'C++',
89		'php'	=> 'PHP',
90		'asm'	=> 'assembly language',
91	);
92	my $line = '';
93	my @maps = split(/,/, $maps);
94	for ($i = 0; $i < @maps; $i++) {
95		$_ = $maps[$i];
96		my($lang, $suffixes) = /([^:]+):(.*)/;
97		if ($i > 0) {
98			if ($i + 1 == @maps) {		# last
99				$line .= ' and ';
100			} else {
101				$line .= ', ';
102			}
103		}
104		$line .= $name{$lang};
105	}
106	$line .= " source files.\n";
107	unshift(@statement, $line);
108	foreach (@maps) {
109		my($lang, $suffixes) = /([^:]+):(.*)/;
110		unless ($name{$lang}) {
111			print STDERR "ERROR: $lang not defined.\n";
112			exit(1);
113		}
114		$suffixes =~ s/^\.//;
115		my(@suffixes) = split(/\./, $suffixes);
116		$line = 'Files whose names end in ';
117		for ($i = 0; $i < @suffixes; $i++) {
118			my $sx = $suffixes[$i];
119			$line .= ', ' if ($i > 0);
120			$line .= "\@file{.$sx}";
121		}
122		$line .= " are assumed to be $name{$lang} source files.\n";
123		unshift(@statement, $line);
124	}
125	@statement;
126}
127#------------------------------------------------------------------
128#
129# Read line.
130#
131#------------------------------------------------------------------
132@lines = ();
133sub getline {
134	if (@lines > 0) {
135		$_ = pop(@lines);
136	} else {
137		while (<INFILE>) {
138			if (/\@LANGMAPSTATEMENT\@/) {
139				@lines = &'langmapstatement();
140				$_ = pop(@lines);
141			} elsif (/\@DEFAULTLANGMAP\@/) {
142				my $value = &'getvalue('DEFAULTLANGMAP');
143				s/\@DEFAULTLANGMAP\@/$value/;
144			} elsif (/\@DEFAULTINCLUDEFILESUFFIXES\@/) {
145				my $value = &'getvalue('DEFAULTINCLUDEFILESUFFIXES');
146				s/\@DEFAULTINCLUDEFILESUFFIXES\@/$value/;
147			}
148			last unless (/^#/);
149		}
150	}
151	($_) ? 1 : 0;
152}
153sub ungetline {
154	push(@lines, $_);
155}
156#------------------------------------------------------------------
157#
158# C package.
159#
160#------------------------------------------------------------------
161package c;
162sub convert {
163	local($arg) = '[^},]+';
164	local($macros) = 'arg|code|var|file|name|option|val|samp|kbd';
165	chop;
166	s/^\s+//;
167	while (s/\@($macros)\{($arg)\}/$2/) {
168		;
169	}
170	while (s/\@xref\{($arg),($arg)\}/$1($2)/) {
171		;
172	}
173	while (s/\@(begin|end)_verbatim//) {
174		;
175	}
176}
177sub gen {
178	local($help_const) = 0;
179	print "/* This file is generated automatically by $'com from $'infile. */\n";
180	while (&'getline()) {
181		if (/^\@NAME\s+(.*)\s+-/) {
182			print "const char *progname = \"$1\";\n";
183		} elsif (/^\@SYNOPSIS$/) {
184			local($first) = 1;
185			print "const char *usage_const = \"";
186			while (&'getline()) {
187				if (/^\@/) {
188					&'ungetline();
189					last;
190				}
191				convert();
192				if ($first) {
193					$first = 0;
194					print "Usage: ";
195				} else {
196					print "\\n\\\n";
197					print "       ";
198				}
199				print $_;
200			}
201			print "\\n\";\n";
202		} elsif (/^\@COMMANDS$/ || /^\@OPTIONS$/) {
203			if (!$help_const) {
204				$help_const = 1;
205				print "const char *help_const = \"";
206			}
207			if (/^\@COMMANDS$/) {
208				print "Commands:";
209			} else {
210				print "Options:";
211			}
212			print "\\n\\\n";
213			local($itemize) = 0;
214			while (&'getline()) {
215				if (/^\@/) {
216					&'ungetline();
217					last;
218				}
219				convert();
220				if (/^\@begin_itemize$/) {
221					$itemize = 1;
222				} elsif (/^\@end_itemize$/) {
223					$itemize = 0;
224				} elsif ($itemize) {
225					if (/^\@item\{(.*)\}$/) {
226						print $1;
227					} else {
228						print "       ";
229						print;
230					}
231					print "\\n\\\n";
232				}
233			}
234		}
235	}
236	print "See also:\\n\\\n";
237	print "       GNU GLOBAL web site: http://www.gnu.org/software/global/\\n\\\n";
238	print "\";\n";
239}
240#------------------------------------------------------------------
241#
242# Man package.
243#
244#------------------------------------------------------------------
245package man;
246sub convert {
247	local($arg) = '[^},]+';
248	s/^\s+//;
249	while (s/\@arg\{($arg)\}/\\fI$1\\fP/) {
250		;
251	}
252	while (/\@code\{($arg)\}/) {
253		$val = $1;
254		$val =~ s/\./\\./g;
255		s/\@code\{$arg\}/$val/;
256	}
257	while (s/\@(val|samp|kbd)\{([^}]+)\}/\\'$2\\'/) {
258		;
259	}
260	while (s/\@file\{($arg)\}/\\'$1\\'/) {
261		;
262	}
263	while (s/\@(var|name|option)\{($arg)\}/\\fB$2\\fP/) {
264		;
265	}
266	while (s/\@xref\{($arg),($arg)\}/\\fB$1\\fP($2)/) {
267		;
268	}
269	s/\@\{/\{/g;
270	s/\@\}/\}/g;
271	s/\@br$/\n.br/;
272	s/\@\@/@/g;
273	s/^\./\\&./;
274}
275sub gen {
276	local($arg) = '[^,]+';
277	print ".\\\" This file is generated automatically by $'com from $'infile.\n";
278	while (&'getline()) {
279		if (/^\@HEADER\s+($arg),($arg),($arg),($arg)\n$/) {
280			print ".TH $1 $2 \"$3\" \"$4\"\n";
281		} elsif (/^\@NAME\s+(.*)$/) {
282			local($name) = $1;
283			$name =~ s/-/\\-/;
284			print ".SH NAME\n$name\n";
285		} elsif (/^\@(SYNOPSIS)$/) {
286			print ".SH $1\n";
287			while (&'getline()) {
288				if (/^\@/) {
289					&'ungetline();
290					last;
291				} elsif (/^$/) {
292					print ".PP\n";
293					next;
294				}
295				convert();
296				print;
297				print ".br\n";
298			}
299		} elsif (/^\@(.*)$/) {
300			$type = $1;
301			if ($type =~ /\s+/) {
302				$type = "\"$type\"";
303			}
304			print ".SH $type\n";
305			local($itemize) = 0;
306			local($verbatim) = 0;
307			while (&'getline()) {
308				if (/^\s*\@begin_verbatim\s*$/) {
309					$verbatim = 1;
310					print ".nf\n";
311					next;
312				} elsif (/^\s*\@end_verbatim\s*$/) {
313					$verbatim = 0;
314					print ".fi\n";
315					next;
316				} elsif (/^\@/) {
317					&'ungetline();
318					last;
319				} elsif (/^$/) {
320					print ".PP\n";
321					next;
322				}
323				convert();
324				if (/^\@begin_itemize$/) {
325					$itemize = 1;
326				} elsif (/^\@end_itemize$/) {
327					$itemize = 0;
328				} elsif ($itemize && /^\@item\{(.*)\}$/) {
329					print ".TP\n$1\n";
330				} else {
331					print;
332				}
333			}
334		}
335	}
336}
337#------------------------------------------------------------------
338#
339# Info package.
340#
341#------------------------------------------------------------------
342package info;
343sub convert {
344	local($arg) = '[^},]+';
345	chop;
346	s/^\s+//;
347	while (s/\@xref\{($arg),($arg)\}/$1($2)/) {
348		;
349	}
350	s/\@option\{/\@samp\{/g;
351	s/\@val\{/\@samp\{/g;
352	while (s/\@(arg|name)\{($arg)\}/$2/) {
353		;
354	}
355	s/\@br$/\@\*/;
356}
357sub gen {
358	print "\@c This file is generated automatically by $'com from $'infile.\n";
359	while (&'getline()) {
360		if (/^\@HEADER/) {
361			;
362		} elsif (/^\@(NAME)\s+(.*)$/) {
363			local($name) = $2;
364			print "\@unnumberedsubsec $1\n";
365			print "$name\n";
366		} elsif (/^\@(SYNOPSIS)$/) {
367			print "\@unnumberedsubsec $1\n";
368			print "\@quotation\n";
369			while (&'getline()) {
370				if (/^\@/) {
371					&'ungetline();
372					last;
373				} elsif (/^$/) {
374					print;
375					next;
376				}
377				convert();
378				print;
379				print "\@*\n";
380			}
381			print "\@end quotation\n";
382		} elsif (/^\@(.*)$/) {
383			$type = $1;
384			print "\@unnumberedsubsec $type\n";
385			local($itemize) = 0;
386			local($verbatim) = 0;
387			while (&'getline()) {
388				if (/^\s*\@begin_verbatim\s*$/) {
389					$verbatim = 1;
390					print "\@example\n";
391					next;
392				} elsif (/^\s*\@end_verbatim\s*$/) {
393					$verbatim = 0;
394					print "\@end example\n";
395					next;
396				} elsif ($verbatim) {
397					s/\{/@\{/g;
398					s/\}/@\}/g;
399					s/^\s+//;
400					print;
401					next;
402				} elsif (/^\@/) {
403					&'ungetline();
404					last;
405				} elsif (/^$/) {
406					print;
407					next;
408				}
409				convert();
410				if (/^\@begin_itemize$/) {
411					$itemize = 1;
412					print "\@table \@asis\n";
413				} elsif (/^\@end_itemize$/) {
414					$itemize = 0;
415					print "\@end table\n";
416				} elsif ($itemize && /^\@item\{(.*)\}$/) {
417					print "\@item $1\n";
418				} else {
419					print "$_\n";
420				}
421			}
422		}
423	}
424}
425#------------------------------------------------------------------
426#
427# Menu package.
428#
429#------------------------------------------------------------------
430package menu;
431sub gen {
432	local(@args) = @_;
433	local($line, $name);
434	foreach $dir (@args) {
435		$infile = "$dir/manual.in";
436		open(INFILE, $infile) || die("cannot open '$infile'\n");
437		while (<INFILE>) {
438			if (/^\@NAME\s+((\S+)\s+\-\s+.*)$/) {
439				$line = $1;
440				$name = $2;
441				last;
442			}
443		}
444		close(INFILE);
445		push(@name, $name);
446		push(@line, $line);
447	}
448	print "\@c This file is generated automatically by $'com from a set of manual.in.\n";
449	print "\@menu\n";
450	for ($i = 0; $i < @name; $i++) {
451		$name = $name[$i];
452		$line = $line[$i];
453		$name .= '::';
454		printf "* %-16s %s\n", $name, $line;
455	}
456	print "\@end menu\n\n";
457	for ($i = 0; $i < @name; $i++) {
458		$name = $name[$i];
459		$line = $line[$i];
460		printf "\@node %s\n", $name;
461		printf "\@section %s\n", $line;
462		printf "\@include $name.ref\n";
463	}
464}
465