+
+def generate_overview_table(output_filename, table_id, section, table_name, title):
+ """
+ Function to generate the Overview Table from the ini files that define
+ the features for each driver.
+
+ The default features for the table and their order is defined by the
+ 'default.ini' file.
+
+ """
+ # Default warning string.
+ warning = 'Warning generate_overview_table()'
+
+ # Get the default features and order from the 'default.ini' file.
+ ini_path = path_join(dirname(output_filename), 'features')
+ config = configparser.ConfigParser()
+ config.optionxform = str
+ config.read(path_join(ini_path, 'default.ini'))
+ default_features = config.items(section)
+
+ # Create a dict of the valid features to validate the other ini files.
+ valid_features = {}
+ max_feature_length = 0
+ for feature in default_features:
+ key = feature[0]
+ valid_features[key] = ' '
+ max_feature_length = max(max_feature_length, len(key))
+
+ # Get a list of driver ini files, excluding 'default.ini'.
+ ini_files = [basename(file) for file in listdir(ini_path)
+ if file.endswith('.ini') and file != 'default.ini']
+ ini_files.sort()
+
+ # Build up a list of the table header names from the ini filenames.
+ pmd_names = []
+ for ini_filename in ini_files:
+ name = ini_filename[:-4]
+ name = name.replace('_vf', 'vf')
+ pmd_names.append(name)
+
+ # Pad the table header names.
+ max_header_len = len(max(pmd_names, key=len))
+ header_names = []
+ for name in pmd_names:
+ if '_vec' in name:
+ pmd, vec = name.split('_')
+ name = '{0:{fill}{align}{width}}vec'.format(pmd,
+ fill='.', align='<', width=max_header_len-3)
+ else:
+ name = '{0:{fill}{align}{width}}'.format(name,
+ fill=' ', align='<', width=max_header_len)
+ header_names.append(name)
+
+ # Create a dict of the defined features for each driver from the ini files.
+ ini_data = {}
+ for ini_filename in ini_files:
+ config = configparser.ConfigParser()
+ config.optionxform = str
+ config.read(path_join(ini_path, ini_filename))
+
+ # Initialize the dict with the default.ini value.
+ ini_data[ini_filename] = valid_features.copy()
+
+ # Check for a valid ini section.
+ if not config.has_section(section):
+ print("{}: File '{}' has no [{}] secton".format(warning,
+ ini_filename,
+ section))
+ continue
+
+ # Check for valid features names.
+ for name, value in config.items(section):
+ if name not in valid_features:
+ print("{}: Unknown feature '{}' in '{}'".format(warning,
+ name,
+ ini_filename))
+ continue
+
+ if value:
+ # Get the first letter only.
+ ini_data[ini_filename][name] = value[0]
+
+ # Print out the RST Driver Overview table from the ini file data.
+ outfile = open(output_filename, 'w')
+ num_cols = len(header_names)
+
+ print_table_css(outfile, table_id)
+ print('.. table:: ' + table_name + '\n', file=outfile)
+ print_table_header(outfile, num_cols, header_names, title)
+ print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
+
+
+def print_table_header(outfile, num_cols, header_names, title):
+ """ Print the RST table header. The header names are vertical. """
+ print_table_divider(outfile, num_cols)
+
+ line = ''
+ for name in header_names:
+ line += ' ' + name[0]
+
+ print_table_row(outfile, title, line)
+
+ for i in range(1, len(header_names[0])):
+ line = ''
+ for name in header_names:
+ line += ' ' + name[i]
+
+ print_table_row(outfile, '', line)
+
+ print_table_divider(outfile, num_cols)
+
+
+def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
+ """ Print out the body of the table. Each row is a NIC feature. """
+
+ for feature, _ in default_features:
+ line = ''
+
+ for ini_filename in ini_files:
+ line += ' ' + ini_data[ini_filename][feature]
+
+ print_table_row(outfile, feature, line)
+
+ print_table_divider(outfile, num_cols)
+
+
+def print_table_row(outfile, feature, line):
+ """ Print a single row of the table with fixed formatting. """
+ line = line.rstrip()
+ print(' {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
+
+
+def print_table_divider(outfile, num_cols):
+ """ Print the table divider line. """
+ line = ' '
+ column_dividers = ['='] * num_cols
+ line += ' '.join(column_dividers)
+
+ feature = '=' * feature_str_len
+
+ print_table_row(outfile, feature, line)
+
+
+def print_table_css(outfile, table_id):
+ template = """
+.. raw:: html
+
+ <style>
+ .wy-nav-content {
+ opacity: .99;
+ }
+ table#idx {
+ cursor: default;
+ overflow: hidden;
+ }
+ table#idx th, table#idx td {
+ text-align: center;
+ }
+ table#idx th {
+ font-size: 72%;
+ white-space: pre-wrap;
+ vertical-align: top;
+ padding: 0.5em 0;
+ min-width: 0.9em;
+ width: 2em;
+ }
+ table#idx col:first-child {
+ width: 0;
+ }
+ table#idx th:first-child {
+ vertical-align: bottom;
+ }
+ table#idx td {
+ font-size: 70%;
+ padding: 1px;
+ }
+ table#idx td:first-child {
+ padding-left: 1em;
+ text-align: left;
+ }
+ table#idx tr:nth-child(2n-1) td {
+ background-color: rgba(210, 210, 210, 0.2);
+ }
+ table#idx th:not(:first-child):hover,
+ table#idx td:not(:first-child):hover {
+ position: relative;
+ }
+ table#idx th:not(:first-child):hover::after,
+ table#idx td:not(:first-child):hover::after {
+ content: '';
+ height: 6000px;
+ top: -3000px;
+ width: 100%;
+ left: 0;
+ position: absolute;
+ z-index: -1;
+ background-color: #ffb;
+ }
+ table#idx tr:hover td {
+ background-color: #ffb;
+ }
+ </style>
+"""
+ print(template.replace("idx", "id%d" % (table_id)), file=outfile)
+
+