1#!/usr/bin/perl
2#------------------------------------------------------------------------------
3#
4# This file is part of BibTool.
5# It is distributed under the GNU General Public License.
6# See the file COPYING for details.
7#
8# (c) 1997-2020 Gerd Neugebauer
9#
10# Net: gene@gerd-neugebauer.de
11#
12# This program is free software; you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation; either version 2, or (at your option)
15# any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program; if not, write to the Free Software
24# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25#
26#*****************************************************************************
27
28foreach $_ (@ARGV)
29{ print STDERR "$_\n";
30  &analyze_file($_);
31}
32
33sub analyze_file
34{ local ($file) = @_;
35  local (%purpose,$name,%function,%macro,%variable,$state);
36
37  open(FD,$file) || return;
38
39  $file =~ s/_/\\_/go;
40  $file =~ s/^\.\.\///o;
41  $file =~ s/^include\///o;
42  $_ = $file;
43  s/[^.a-zA-Z0-9]//go;
44
45  if    ( /\.c$/ ) { print "\n\\Module{$file}{$_}\n\n"; }
46  elsif ( /\.h$/ ) { print "\n\\Header{$file}{$_}\n\n"; }
47  else             { print "\n\\File{$file}{$_}\n\n"; }
48
49  $state = 0;
50  while (<FD>)
51  {
52    if (/^\*\*/o)
53    {
54      if (/^\*\* Function:[ 	]*([a-zA-Z0-9_]+)/o)
55      { $name = $1;
56	$name =~ s/_/\\_/go;
57	$source{$name}   = $file;
58	$type{$name}     = 0;
59	$function{$name} = 1
60      }
61      elsif (/^\*\* Macro:[ 	]*([a-zA-Z0-9_]+)/o)
62      { $name = $1;
63	$name =~ s/_/\\_/go;
64	$source{$name} = $file;
65	$type{$name}   = 10;
66	$macro{$name}  = 1;
67      }
68      elsif (/^\*\* Constant:[ 	]*([a-zA-Z0-9_]+)/o)
69      { $name = $1;
70	$name =~ s/_/\\_/go;
71	$source{$name} = $file;
72	$type{$name}   = 11;
73	$macro{$name}  = 1;
74      }
75      elsif (/^\*\* Typedef:[ 	]*([a-zA-Z0-9_]+)/o)
76      { $name = $1;
77	$name =~ s/_/\\_/go;
78	$source{$name} = $file;
79	$type{$name}   = 22;
80      }
81      elsif (/^\*\* Type:[ 	]*([%* a-zA-Z0-9_]+)/o)
82      { $head{$name} = "$1 \\Mac{$name}";
83      }
84      elsif (/^\*\* Variable:[ 	]*([a-zA-Z0-9_]+)/o)
85      { $name = $1;
86	$name =~ s/_/\\_/go;
87	$source{$name}    = $file;
88	$type{$name}      = 1;
89	$variable{$name}  = 1;
90      }
91      elsif (/^\*\*[ 	]*Description:[ 	]*([a-zA-Z0-9_]*)/o)
92      { print $1."\n" if $1 ne '';
93	$state = 9;
94      }
95      elsif ($name eq '' && $state == 0 )
96      {
97      }
98      elsif (/^\*\* Arguments:/o)
99      { $state = 2;
100	@a = ();
101      }
102      elsif (/^\*\* Returns:[ 	]*(.*)/o)
103      { $returns{$name} = '    '.$1;
104	$state   = 3;
105      }
106      elsif (/^\*\* Purpose:[ 	]*(.*)/o)
107      { $_ = $1;
108	s/_/\\_/go;
109	$purpose{$name} = '  '.$_;
110	$state   = 1;
111      }
112      elsif (/^\*\* Example:[ 	]*(.*)/o)
113      { $_ = $1;
114	s/_/\\_/go;
115	$example{$name} = '  '.$_;
116	$state   = 5;
117      }
118      elsif ( /^\*\*[-*_]/o )
119      { $state = 0;
120	if ( $type{$name} == 10 )
121	{ $_ = $name;
122	  s/\\_//go;
123	  if ( $head{$name} eq '' ) { $n = "\\Mac{$name}"; }
124	  else { $n = $head{$name}; }
125	  $n =~ s/([^\\])_/$1\\_/g;
126	  print "\\begin{Macro}{$n}{$_}\n  \\begin{Arguments}";
127	  foreach $a (@a)
128	  { print "\n    & \\Var{$a} & $arg{$a}\\\\";
129	  }
130	  print "\n  \\end{Arguments}%\n";
131	  print "$purpose{$name}\n";
132	  print "  \\begin{Result}\n$returns{$name}\n  \\end{Result}\n"
133	      if ($returns{$name} ne '');
134	  print "\\end{Macro}\n";
135	  $name = '';
136	}
137	elsif ( $type{$name} == 11 )
138	{ $_ = $name;
139	  s/\\_//go;
140	  if ( $head{$name} eq '' ) { $n = "\\Mac{$name}"; }
141	  else { $n = $head{$name}; }
142	  print "\\begin{Constant}{$n}{$_}\n";
143	  print "\n  \\begin{Arguments}$arg{$name}\n  \\end{Arguments}%\n"
144	      if ($arg{$name} ne '');
145	  print "$purpose{$name}\n";
146	  print "\\end{Constant}\n";
147	  $name = '';
148	}
149	elsif ( $type{$name} == 1 )
150	{ $_ = $name;
151	  s/\\_//go;
152	  if ( $head{$name} eq '' ) { $n = "\\Mac{$name}"; }
153	  else { $n = $head{$name}; }
154	  print "\\begin{Variable}{$n}{$_}\n";
155	  print "$purpose{$name}\n";
156	  print "\\end{Variable}\n";
157	  $name = '';
158	}
159	elsif ( $type{$name} == 22 )
160	{ $_ = $name;
161	  s/\\_//go;
162	  if ( $head{$name} eq '' ) { $n = "\\Type{$name}"; }
163	  else { $n = $head{$name}; }
164	  print "\\begin{Typedef}{$n}{$_}\n";
165	  print "$purpose{$name}\n";
166	  $name  = '';
167	  $state = 22;
168	}
169      }
170      elsif ( $state == 9 && /^\*\*[ 	]*(.*)/o )
171      { print $1."\n";
172      }
173      elsif ( $state == 1 && /^\*\*[ 	]*(.*)/o )
174      { $purpose{$name} = $purpose{$name}."\n  ".$1;
175      }
176      elsif ( $state == 2 && /^\*\*		(.*)/o )
177      { $arg{$lastarg} = $arg{$lastarg}."\n".$1;
178      }
179      elsif ( $state == 2 && /^\*\*[ 	]+([a-zA-Z0-9_]+)[ 	]*(.*)/o )
180      { $arg{$1} = $2;
181	$lastarg = $1;
182	push (@a,($1));
183      }
184      elsif ( $state == 3 && /^\*\*[ 	]*(.*)/o )
185      { $returns{$name} = $returns{$name}."\n    ".$1;
186      }
187    }
188    elsif ( /^([a-zA-Z_][^(]*[^a-zA-Z0-9_(])([a-zA-Z0-9_]*)/o && $state == 0 )
189    { $_ = "$1\\Fct{$2}";
190      if ( /^static/ )
191      { undef $purpose{$name};
192      }
193      else
194      {
195	s/_/\\_/go;
196	$head{$name}  = $_;
197	$proto{$name} = '';
198	$state = 11;
199      }
200    }
201    elsif ( $state == 11 && /^[ 	]+([^;]*;)/o )
202    { $_ = $1;
203      s/register //o;
204      s/[ 	]+/ /go;
205      s/_ARG\((.*)\)/$1/o;
206      if ( /^(.*\([^a-zA-Z0-9_]*)([a-zA-Z0-9_]+)(\)\(.*\);)$/o )
207      { $_ = "$1\\ \t&\\Var{$2}$3 \t&$arg{$2}";
208      }
209      else
210      { s/([a-zA-Z0-9_]+)(\[[0-9a-zA-Z_]*\])?;/\\ \t&\\Var{$1}$2;\t&$arg{$1}/o;
211      }
212      s/_/\\_/go;
213      if ($proto{$name} eq '')
214      {	$proto{$name} = "\n    ".$_; }
215      else
216      {	$proto{$name} = $proto{$name}."\\\\\n    ".$_; }
217    }
218    elsif ( $state == 22 )
219    { if ( /^[ ]*typedef[ ]*struct[ ]*([a-zA-Z_0-9]+|)/o )
220      { print "  \\STRUCT{$1}\n";
221	$NL = '';
222      } elsif (/^[ ]*}[ ]*(.*[a-zA-Z])[ ]*;/o)
223      { $x = '';
224	foreach $_ (split(/,[ ]*/,$1))
225	{ $x = $x . ', ' if ( $x ne '');
226	  $x = $x . "\\Type{$_}";
227	}
228	print "\n  \\EndSTRUCT{$x}\n\\end{Typedef}\n";
229	$state = 0;
230      } elsif ( /^[ {]*([a-zA-Z_][^(]*[^a-zA-Z0-9_(])([a-zA-Z0-9_]+);[ 	]*\/\*[ 	]*(.*)\*\//o )
231      { $_ = $2;
232	$t = $1;
233	$c = $3;
234	s/_/\\_/go;
235	$t =~ s/_/\\_/g;
236	print "$NL    $t\\ \t&\\Member{$_};\t& $c";
237	$NL = "\\\\\n";
238      } elsif ( /^[ {]*([a-zA-Z_][^(]*[^a-zA-Z0-9_(])([a-zA-Z0-9_]+);/o )
239      { $_ = $2;
240	$t = $1;
241	s/_/\\_/;
242	print "$NL    $t\\ \t&\\Member{$_};\t& ";
243	$NL = "\\\\\n";
244      } elsif ( /^[ 	]*\/\*[ 	]*(.*)\*\//o )
245      { print "\n\t\t\t$1";
246      } else
247      { print $_;
248      }
249    }
250    elsif ( /^{/o && $name ne '' )
251    {
252      $name  = '';
253      $state = 0;
254    }
255  }
256
257  foreach $_ (sort(keys %function))
258  {
259    if ( $_ ne '' && $head{$_} ne '' )
260    { print "\\begin{Function}{$head{$_}}{$_}";
261      print "\n  \\begin{Arguments}$proto{$_}\n  \\end{Arguments}%\n"
262	  if ($proto{$_} ne '');
263      print "$purpose{$_}\n";
264      print "  \\begin{Result}\n$returns{$_}\n  \\end{Result}\n";
265      print "\\end{Function}\n";
266    }
267  }
268
269  close(FD);
270}
271
272#------------------------------------------------------------------------------
273# Local Variables:
274# mode: perl
275# End:
276