2 # vim: ft=perl ts=2 sts=2 sw=2 et ai
3 # -*- Mode: perl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along
17 # with this program; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 # Copyright 2014 Red Hat, Inc.
25 # The script parses nm-setting-*.c files and extracts documentation related
26 # to setting plugins. The documentation is in a simple format of lines
27 # "keyword: value". The documentation is enclosed between tags
28 # ---<plugin-name>--- and ---end---
29 # Recognized keywords are:
30 # "property: " - property name
31 # "variable: " - name of the variable used by the plugin
32 # "format: " - format of the value in 'keyfile' plugin
33 # "default: " - default value when variable is not used
34 # "values: " - allowed values (e.g. for enumerations)
35 # "example: " - example(s)
36 # "description: " - description text
37 # Value is an arbitrary string that can span over multiple lines.
40 # - mark NM extension variables with (+), e.g. variable: UUID(+)
46 #YAML:XS is based on libyaml C library and it is a good and fast YAML implementation.
47 #However it may not be present everywhere. So use YAML instead.
48 #use YAML::XS qw(Load);
52 my @keywords = ("property", "variable", "format", "values", "default", "example", "description");
57 (scalar @ARGV == 3) or die "Usage: $0 <plugin> <srcdir> <output-xml-file>\n";
58 my ($plugin, $srcdir, $output) = @ARGV;
59 my $start_tag = "---$plugin---\\s*\$";
60 my $end_tag = '---end---';
62 # get source files to scan for documentation comments (nm-setting-<something>.c)
63 my $file = "$srcdir/Makefile.libnm-core";
64 open my $fh, '<', $file or die "Can't open $file: $!";
65 while (my $line = <$fh>) {
67 my @strings = $line =~ /\/(nm-setting-[^.]*\.c)(?:\s|$)/g;
68 push @source_files, @strings
73 open $fo, '>', $output or die "Can't open $output: $!";
78 # write generated documenation for each setting
79 foreach my $c_file (@source_files) {
80 my $path = "$srcdir/$c_file";
81 my $setting_name = get_setting_name($path);
82 write_item("<setting name=\"$setting_name\">");
83 scan_doc_comments($path, $start_tag, $end_tag);
84 write_item("</setting>");
94 ### --- subroutines --- ###
96 # get setting name from NM_SETTING_*_SETTING_NAME constant in C header file
97 sub get_setting_name {
99 $path =~ s/c$/h/; # use header file to find out setting name
100 open my $fh, '<', $path or die "Can't open $path: $!";
101 while (my $line = <$fh>) {
102 if ($line =~ /NM_SETTING_.+SETTING_NAME\s+\"(\S+)\"/) {
108 # scan source setting file for documentation tags and write them to XML
109 sub scan_doc_comments {
110 my($setting_file, $start, $end) = @_;
111 open my $fi, '<', $setting_file or die "Can't open $setting_file: $!";
113 if (/$start/ .. /$end/) {
122 # ignore text not inside marks
127 # process plugin property documentation comments (as a YAML document)
130 my $kwd_pat = join("|", @keywords);
131 my $yaml_literal_seq = "|\n";
134 # make a proper YAML document from @data
135 $_ =~ s/^\s*\**\s+|\s+$//; # remove leading spaces and *, and traling spaces
136 # Properly indent the text so that it is a valid YAML, and insert | (for literal text)
137 if ($_ =~ /^($kwd_pat):\s+/) {
138 # add | after "keyword:" that allows using literal text (YAML won't break on special character)
139 # http://learnxinyminutes.com/docs/yaml/ and http://www.yaml.org/spec/1.2/spec.html#id2795688
140 $_ =~ s/(^($kwd_pat):)/$1 $yaml_literal_seq/;
142 $_ = " " . $_; # indent the text
145 my $str = join ("", @data);
146 my $yaml_data = Load($str);
148 # now write a line into the XML
149 my $name = $yaml_data->{property} // "";
150 my $var = $yaml_data->{variable} // $name; # fallback to "property: "
151 my $format = $yaml_data->{format} // "";
152 my $values = $yaml_data->{values} // "";
153 my $def = $yaml_data->{default} // "";
154 my $exam = $yaml_data->{example} // "";
155 my $desc = $yaml_data->{description} // "";
157 chomp($name, $var, $format, $values, $def, $exam, $desc);
158 escape_xml_chars($name, $var, $format, $values, $def, $exam, $desc);
159 my $foo = sprintf("<property name=\"%s\" variable=\"%s\" format=\"%s\" values=\"%s\" ".
160 "default=\"%s\" example=\"%s\" description=\"%s\"/>",
161 $name, $var, $format, $values, $def, $exam, $desc);
169 qq{<?xml version=\"1.0\"?>
170 <!DOCTYPE nm-$plugin-docs [
179 my $footer = "</nm-$plugin-docs>";
184 my $str = join("", @_);
185 print {$fo} $str, "\n";
188 sub escape_xml_chars {
189 # http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Predefined%5Fentities%5Fin%5FXML
190 foreach my $val (@_) {
191 $val =~ s/&/&/sg;
194 $val =~ s/"/"/sg;
195 $val =~ s/'/'/sg;