1# BSD LICENSE 2# Copyright(c) 2010-2015 Intel Corporation. All rights reserved. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions 7# are met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in 13# the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Intel Corporation nor the names of its 16# contributors may be used to endorse or promote products derived 17# from this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31from __future__ import print_function 32import subprocess 33from docutils import nodes 34from distutils.version import LooseVersion 35from sphinx import __version__ as sphinx_version 36from sphinx.highlighting import PygmentsBridge 37from pygments.formatters.latex import LatexFormatter 38from os import listdir 39from os.path import basename 40from os.path import dirname 41from os.path import join as path_join 42 43try: 44 # Python 2. 45 import ConfigParser as configparser 46except: 47 # Python 3. 48 import configparser 49 50 51project = 'Data Plane Development Kit' 52 53if LooseVersion(sphinx_version) >= LooseVersion('1.3.1'): 54 html_theme = "sphinx_rtd_theme" 55html_logo = '../logo/DPDK_logo_vertical_rev_small.png' 56latex_logo = '../logo/DPDK_logo_horizontal_tag.png' 57html_add_permalinks = "" 58html_show_copyright = False 59highlight_language = 'none' 60 61version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion']).decode('utf-8').rstrip() 62release = version 63 64master_doc = 'index' 65 66# Figures, tables and code-blocks automatically numbered if they have caption 67numfig = True 68 69latex_documents = [ 70 ('index', 71 'doc.tex', 72 '', 73 '', 74 'manual') 75] 76 77# Latex directives to be included directly in the latex/pdf docs. 78latex_preamble = r""" 79\usepackage[utf8]{inputenc} 80\usepackage[T1]{fontenc} 81\usepackage{helvet} 82\renewcommand{\familydefault}{\sfdefault} 83\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm} 84""" 85 86# Configuration for the latex/pdf docs. 87latex_elements = { 88 'papersize': 'a4paper', 89 'pointsize': '11pt', 90 # remove blank pages 91 'classoptions': ',openany,oneside', 92 'babel': '\\usepackage[english]{babel}', 93 # customize Latex formatting 94 'preamble': latex_preamble 95} 96 97# Override the default Latex formatter in order to modify the 98# code/verbatim blocks. 99class CustomLatexFormatter(LatexFormatter): 100 def __init__(self, **options): 101 super(CustomLatexFormatter, self).__init__(**options) 102 # Use the second smallest font size for code/verbatim blocks. 103 self.verboptions = r'formatcom=\footnotesize' 104 105# Replace the default latex formatter. 106PygmentsBridge.latex_formatter = CustomLatexFormatter 107 108######## :numref: fallback ######## 109# The following hook functions add some simple handling for the :numref: 110# directive for Sphinx versions prior to 1.3.1. The functions replace the 111# :numref: reference with a link to the target (for all Sphinx doc types). 112# It doesn't try to label figures/tables. 113 114def numref_role(reftype, rawtext, text, lineno, inliner): 115 """ 116 Add a Sphinx role to handle numref references. Note, we can't convert 117 the link here because the doctree isn't build and the target information 118 isn't available. 119 """ 120 # Add an identifier to distinguish numref from other references. 121 newnode = nodes.reference('', 122 '', 123 refuri='_local_numref_#%s' % text, 124 internal=True) 125 return [newnode], [] 126 127def process_numref(app, doctree, from_docname): 128 """ 129 Process the numref nodes once the doctree has been built and prior to 130 writing the files. The processing involves replacing the numref with a 131 link plus text to indicate if it is a Figure or Table link. 132 """ 133 134 # Iterate over the reference nodes in the doctree. 135 for node in doctree.traverse(nodes.reference): 136 target = node.get('refuri', '') 137 138 # Look for numref nodes. 139 if target.startswith('_local_numref_#'): 140 target = target.replace('_local_numref_#', '') 141 142 # Get the target label and link information from the Sphinx env. 143 data = app.builder.env.domains['std'].data 144 docname, label, _ = data['labels'].get(target, ('', '', '')) 145 relative_url = app.builder.get_relative_uri(from_docname, docname) 146 147 # Add a text label to the link. 148 if target.startswith('figure'): 149 caption = 'Figure' 150 elif target.startswith('table'): 151 caption = 'Table' 152 else: 153 caption = 'Link' 154 155 # New reference node with the updated link information. 156 newnode = nodes.reference('', 157 caption, 158 refuri='%s#%s' % (relative_url, label), 159 internal=True) 160 node.replace_self(newnode) 161 162 163def generate_nic_overview_table(output_filename): 164 """ 165 Function to generate the NIC Overview Table from the ini files that define 166 the features for each NIC. 167 168 The default features for the table and their order is defined by the 169 'default.ini' file. 170 171 """ 172 # Default worning string. 173 warning = 'Warning generate_nic_overview_table()' 174 175 # Get the default features and order from the 'default.ini' file. 176 ini_path = path_join(dirname(output_filename), 'features') 177 config = configparser.ConfigParser() 178 config.optionxform = str 179 config.read(path_join(ini_path, 'default.ini')) 180 default_section = 'Features' 181 default_features = config.items(default_section) 182 183 # Create a dict of the valid features to validate the other ini files. 184 valid_features = {} 185 max_feature_length = 0 186 for feature in default_features: 187 key = feature[0] 188 valid_features[key] = ' ' 189 max_feature_length = max(max_feature_length, len(key)) 190 191 # Get a list of NIC ini files, excluding 'default.ini'. 192 ini_files = [basename(file) for file in listdir(ini_path) 193 if file.endswith('.ini') and file != 'default.ini'] 194 ini_files.sort() 195 196 # Build up a list of the table header names from the ini filenames. 197 header_names = [] 198 for ini_filename in ini_files: 199 name = ini_filename[:-4] 200 name = name.replace('_vf', 'vf') 201 202 # Pad the table header names to match the existing format. 203 if '_vec' in name: 204 pmd, vec = name.split('_') 205 name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<') 206 else: 207 name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<') 208 209 header_names.append(name) 210 211 # Create a dict of the defined features for each NIC from the ini files. 212 ini_data = {} 213 for ini_filename in ini_files: 214 config = configparser.ConfigParser() 215 config.optionxform = str 216 config.read(path_join(ini_path, ini_filename)) 217 218 # Initialize the dict with the default.ini value. 219 ini_data[ini_filename] = valid_features.copy() 220 221 # Check for a valid ini section. 222 if not config.has_section(default_section): 223 print("{}: File '{}' has no [{}] secton".format(warning, 224 ini_filename, 225 default_section)) 226 continue 227 228 # Check for valid features names. 229 for name, value in config.items(default_section): 230 if name not in valid_features: 231 print("{}: Unknown feature '{}' in '{}'".format(warning, 232 name, 233 ini_filename)) 234 continue 235 236 if value is not '': 237 # Get the first letter only. 238 ini_data[ini_filename][name] = value[0] 239 240 # Print out the RST NIC Overview table from the ini file data. 241 outfile = open(output_filename, 'w') 242 num_cols = len(header_names) 243 244 print('.. table:: Features availability in networking drivers\n', 245 file=outfile) 246 247 print_table_header(outfile, num_cols, header_names) 248 print_table_body(outfile, num_cols, ini_files, ini_data, default_features) 249 250 251def print_table_header(outfile, num_cols, header_names): 252 """ Print the RST table header. The header names are vertical. """ 253 print_table_divider(outfile, num_cols) 254 255 line = '' 256 for name in header_names: 257 line += ' ' + name[0] 258 259 print_table_row(outfile, 'Feature', line) 260 261 for i in range(1, 10): 262 line = '' 263 for name in header_names: 264 line += ' ' + name[i] 265 266 print_table_row(outfile, '', line) 267 268 print_table_divider(outfile, num_cols) 269 270 271def print_table_body(outfile, num_cols, ini_files, ini_data, default_features): 272 """ Print out the body of the table. Each row is a NIC feature. """ 273 274 for feature, _ in default_features: 275 line = '' 276 277 for ini_filename in ini_files: 278 line += ' ' + ini_data[ini_filename][feature] 279 280 print_table_row(outfile, feature, line) 281 282 print_table_divider(outfile, num_cols) 283 284 285def print_table_row(outfile, feature, line): 286 """ Print a single row of the table with fixed formatting. """ 287 line = line.rstrip() 288 print(' {:<20}{}'.format(feature, line), file=outfile) 289 290 291def print_table_divider(outfile, num_cols): 292 """ Print the table divider line. """ 293 line = ' ' 294 column_dividers = ['='] * num_cols 295 line += ' '.join(column_dividers) 296 297 feature = '=' * 20 298 299 print_table_row(outfile, feature, line) 300 301 302def setup(app): 303 generate_nic_overview_table('doc/guides/nics/overview_table.txt') 304 305 if LooseVersion(sphinx_version) < LooseVersion('1.3.1'): 306 print('Upgrade sphinx to version >= 1.3.1 for ' 307 'improved Figure/Table number handling.') 308 # Add a role to handle :numref: references. 309 app.add_role('numref', numref_role) 310 # Process the numref references once the doctree has been created. 311 app.connect('doctree-resolved', process_numref) 312