scripts: Switch to more portable Perl shebang
[linux-block.git] / scripts / kernel-doc-xml-ref
1 #!/usr/bin/env perl
2
3 use warnings;
4 use strict;
5
6 ## Copyright (C) 2015  Intel Corporation                         ##
7 #                                                                ##
8 ## This software falls under the GNU General Public License.     ##
9 ## Please read the COPYING file for more information             ##
10 #
11 #
12 # This software reads a XML file and a list of valid interal
13 # references to replace Docbook tags with links.
14 #
15 # The list of "valid internal references" must be one-per-line in the following format:
16 #      API-struct-foo
17 #      API-enum-bar
18 #      API-my-function
19 #
20 # The software walks over the XML file looking for xml tags representing possible references
21 # to the Document. Each reference will be cross checked against the "Valid Internal Reference" list. If
22 # the referece is found it replaces its content by a <link> tag.
23 #
24 # usage:
25 # kernel-doc-xml-ref -db filename
26 #                    xml filename > outputfile
27
28 # read arguments
29 if ($#ARGV != 2) {
30         usage();
31 }
32
33 #Holds the database filename
34 my $databasefile;
35 my @database;
36
37 #holds the inputfile
38 my $inputfile;
39 my $errors = 0;
40
41 my %highlights = (
42         "<function>(.*?)</function>",
43             "\"<function>\" . convert_function(\$1, \$line) . \"</function>\"",
44         "<structname>(.*?)</structname>",
45             "\"<structname>\" . convert_struct(\$1) . \"</structname>\"",
46         "<funcdef>(.*?)<function>(.*?)</function></funcdef>",
47             "\"<funcdef>\" . convert_param(\$1) . \"<function>\$2</function></funcdef>\"",
48         "<paramdef>(.*?)<parameter>(.*?)</parameter></paramdef>",
49             "\"<paramdef>\" . convert_param(\$1) . \"<parameter>\$2</parameter></paramdef>\"");
50
51 while($ARGV[0] =~ m/^-(.*)/) {
52         my $cmd = shift @ARGV;
53         if ($cmd eq "-db") {
54                 $databasefile = shift @ARGV
55         } else {
56                 usage();
57         }
58 }
59 $inputfile = shift @ARGV;
60
61 sub open_database {
62         open (my $handle, '<', $databasefile) or die "Cannot open $databasefile";
63         chomp(my @lines = <$handle>);
64         close $handle;
65
66         @database = @lines;
67 }
68
69 sub process_file {
70         open_database();
71
72         my $dohighlight;
73         foreach my $pattern (keys %highlights) {
74                 $dohighlight .=  "\$line =~ s:$pattern:$highlights{$pattern}:eg;\n";
75         }
76
77         open(FILE, $inputfile) or die("Could not open $inputfile") or die ("Cannot open $inputfile");
78         foreach my $line (<FILE>)  {
79                 eval $dohighlight;
80                 print $line;
81         }
82 }
83
84 sub trim($_)
85 {
86         my $str = $_[0];
87         $str =~ s/^\s+|\s+$//g;
88         return $str
89 }
90
91 sub has_key_defined($_)
92 {
93         if ( grep( /^$_[0]$/, @database)) {
94                 return 1;
95         }
96         return 0;
97 }
98
99 # Gets a <function> content and add it a hyperlink if possible.
100 sub convert_function($_)
101 {
102         my $arg = $_[0];
103         my $key = $_[0];
104
105         my $line = $_[1];
106
107         $key = trim($key);
108
109         $key =~ s/[^A-Za-z0-9]/-/g;
110         $key = "API-" . $key;
111
112         # We shouldn't add links to <funcdef> prototype
113         if (!has_key_defined($key) || $line =~ m/\s+<funcdef/i) {
114                 return $arg;
115         }
116
117         my $head = $arg;
118         my $tail = "";
119         if ($arg =~ /(.*?)( ?)$/) {
120                 $head = $1;
121                 $tail = $2;
122         }
123         return "<link linkend=\"$key\">$head</link>$tail";
124 }
125
126 # Converting a struct text to link
127 sub convert_struct($_)
128 {
129         my $arg = $_[0];
130         my $key = $_[0];
131         $key =~ s/(struct )?(\w)/$2/g;
132         $key =~ s/[^A-Za-z0-9]/-/g;
133         $key = "API-struct-" . $key;
134
135         if (!has_key_defined($key)) {
136                 return $arg;
137         }
138
139         my ($head, $tail) = split_pointer($arg);
140         return "<link linkend=\"$key\">$head</link>$tail";
141 }
142
143 # Identify "object *" elements
144 sub split_pointer($_)
145 {
146         my $arg = $_[0];
147         if ($arg =~ /(.*?)( ?\* ?)/) {
148                 return ($1, $2);
149         }
150         return ($arg, "");
151 }
152
153 sub convert_param($_)
154 {
155         my $type = $_[0];
156         my $keyname = convert_key_name($type);
157
158         if (!has_key_defined($keyname)) {
159                 return $type;
160         }
161
162         my ($head, $tail) = split_pointer($type);
163         return "<link linkend=\"$keyname\">$head</link>$tail";
164
165 }
166
167 # DocBook links are in the API-<TYPE>-<STRUCT-NAME> format
168 # This method gets an element and returns a valid DocBook reference for it.
169 sub convert_key_name($_)
170 {
171         #Pattern $2 is optional and might be uninitialized
172         no warnings 'uninitialized';
173
174         my $str = $_[0];
175         $str =~ s/(const|static)? ?(struct)? ?([a-zA-Z0-9_]+) ?(\*|&)?/$2 $3/g ;
176
177         # trim
178         $str =~ s/^\s+|\s+$//g;
179
180         # spaces and _ to -
181         $str =~ s/[^A-Za-z0-9]/-/g;
182
183         return "API-" . $str;
184 }
185
186 sub usage {
187         print "Usage: $0 -db database filename\n";
188         print "         xml source file(s) > outputfile\n";
189         exit 1;
190 }
191
192 # starting point
193 process_file();
194
195 if ($errors) {
196         print STDERR "$errors errors\n";
197 }
198
199 exit($errors);