blob: de34632090d5df60dd573b8d9d4fda4383e3ec82 [file] [log] [blame]
Tobin Ehlis3198ba32017-04-19 17:30:52 -06001#!/usr/bin/python -i
Tobin Ehlis5ade0692016-10-05 17:18:15 -06002
3import sys
Mark Lobodzinski8c9633d2017-06-05 13:50:10 -06004try:
5 import urllib.request as urllib2
6except ImportError:
7 import urllib2
Tobin Ehlis3198ba32017-04-19 17:30:52 -06008from bs4 import BeautifulSoup
Tobin Ehlis98d109a2017-05-11 14:42:38 -06009import json
10import vuid_mapping
Tobin Ehlis5ade0692016-10-05 17:18:15 -060011
12#############################
13# spec.py script
14#
Tobin Ehlisda3916c2017-05-24 14:13:46 -060015# Overview - this script is intended to generate validation error codes and message strings from the json spec file
16# that contains all of the valid usage statements. In addition to generating the header file, it provides a number of
17# corrollary services to aid in generating/updating the header.
Tobin Ehlis5ade0692016-10-05 17:18:15 -060018#
Tobin Ehlisda3916c2017-05-24 14:13:46 -060019# Ideal flow - Pull the valid usage text and IDs from the spec json, pull the IDs from the validation error database,
20# then update the database with any new IDs from the json file and generate new database and header file.
Tobin Ehlis5ade0692016-10-05 17:18:15 -060021#
22# TODO:
Tobin Ehlisda3916c2017-05-24 14:13:46 -060023# 1. When VUs go away (in error DB, but not in json) need to report them and remove from DB as deleted
Tobin Ehlis5ade0692016-10-05 17:18:15 -060024#
25#############################
26
27
Mark Lobodzinskie3787b42017-06-21 13:41:00 -060028out_filename = "../layers/vk_validation_error_messages.h" # can override w/ '-out <filename>' option
29db_filename = "../layers/vk_validation_error_database.txt" # can override w/ '-gendb <filename>' option
Tobin Ehlis2c932132017-05-19 16:32:15 -060030json_filename = None # con pass in w/ '-json <filename> option
Tobin Ehlis5ade0692016-10-05 17:18:15 -060031gen_db = False # set to True when '-gendb <filename>' option provided
Tobin Ehlis2c932132017-05-19 16:32:15 -060032json_compare = False # compare existing DB to json file input
Tobin Ehlis828781a2017-05-23 15:23:40 -060033json_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/validation/validusage.json"
34read_json = False
Tobin Ehlis5ade0692016-10-05 17:18:15 -060035# This is the root spec link that is used in error messages to point users to spec sections
Tobin Ehlisbd0a9c62016-10-14 18:06:16 -060036#old_spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html"
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060037spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
Tobin Ehlis828781a2017-05-23 15:23:40 -060038core_url = "https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html"
39ext_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
Tobin Ehlis5ade0692016-10-05 17:18:15 -060040# After the custom validation error message, this is the prefix for the standard message that includes the
41# spec valid usage language as well as the link to nearest section of spec to that language
Tobin Ehlisda3916c2017-05-24 14:13:46 -060042error_msg_prefix = "The spec valid usage text states "
Mark Lobodzinski629d47b2016-10-18 13:34:58 -060043validation_error_enum_name = "VALIDATION_ERROR_"
Tobin Ehlis5ade0692016-10-05 17:18:15 -060044
45def printHelp():
Tobin Ehlisda3916c2017-05-24 14:13:46 -060046 print ("Usage: python spec.py [-out <headerfile.h>] [-gendb <databasefile.txt>] [-update] [-json <json_file>] [-help]")
Tobin Ehlis3198ba32017-04-19 17:30:52 -060047 print ("\n Default script behavior is to parse the specfile and generate a header of unique error enums and corresponding error messages based on the specfile.\n")
48 print (" Default specfile is from online at %s" % (spec_url))
49 print (" Default headerfile is %s" % (out_filename))
50 print (" Default databasefile is %s" % (db_filename))
51 print ("\nIf '-gendb' option is specified then a database file is generated to default file or <databasefile.txt> if supplied. The database file stores")
52 print (" the list of enums and their error messages.")
Tobin Ehlis3198ba32017-04-19 17:30:52 -060053 print ("\nIf '-update' option is specified this triggers the master flow to automate updating header and database files using default db file as baseline")
54 print (" and online spec file as the latest. The default header and database files will be updated in-place for review and commit to the git repo.")
Tobin Ehlis828781a2017-05-23 15:23:40 -060055 print ("\nIf '-json' option is used trigger the script to load in data from a json file.")
56 print ("\nIf '-json-file' option is it will point to a local json file, else '%s' is used from the web." % (json_url))
Tobin Ehlis5ade0692016-10-05 17:18:15 -060057
Tobin Ehlis3c37fb32017-05-24 09:31:13 -060058def get8digithex(dec_num):
59 """Convert a decimal # into an 8-digit hex"""
60 if dec_num > 4294967295:
61 print ("ERROR: Decimal # %d can't be represented in 8 hex digits" % (dec_num))
62 sys.exit()
63 hex_num = hex(dec_num)
64 return hex_num[2:].zfill(8)
65
Tobin Ehlis5ade0692016-10-05 17:18:15 -060066class Specification:
67 def __init__(self):
68 self.tree = None
Tobin Ehlis5ade0692016-10-05 17:18:15 -060069 self.error_db_dict = {} # dict of previous error values read in from database file
70 self.delimiter = '~^~' # delimiter for db file
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060071 # Global dicts used for tracking spec updates from old to new VUs
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060072 self.orig_no_link_msg_dict = {} # Pair of API,Original msg w/o spec link to ID list mapping
73 self.orig_core_msg_dict = {} # Pair of API,Original core msg (no link or section) to ID list mapping
74 self.last_mapped_id = -10 # start as negative so we don't hit an accidental sequence
75 self.orig_test_imp_enums = set() # Track old enums w/ tests and/or implementation to flag any that aren't carried fwd
Tobin Ehlis2c932132017-05-19 16:32:15 -060076 # Dict of data from json DB
77 # Key is API,<short_msg> which leads to dict w/ following values
78 # 'ext' -> <core|<ext_name>>
79 # 'string_vuid' -> <string_vuid>
80 # 'number_vuid' -> <numerical_vuid>
81 self.json_db = {}
82 self.json_missing = 0
83 self.struct_to_func_map = {} # Map structs to the API func that they fall under in the spec
84 self.duplicate_json_key_count = 0
Tobin Ehlis5ade0692016-10-05 17:18:15 -060085 self.copyright = """/* THIS FILE IS GENERATED. DO NOT EDIT. */
86
87/*
88 * Vulkan
89 *
90 * Copyright (c) 2016 Google Inc.
Mark Lobodzinski629d47b2016-10-18 13:34:58 -060091 * Copyright (c) 2016 LunarG, Inc.
Tobin Ehlis5ade0692016-10-05 17:18:15 -060092 *
93 * Licensed under the Apache License, Version 2.0 (the "License");
94 * you may not use this file except in compliance with the License.
95 * You may obtain a copy of the License at
96 *
97 * http://www.apache.org/licenses/LICENSE-2.0
98 *
99 * Unless required by applicable law or agreed to in writing, software
100 * distributed under the License is distributed on an "AS IS" BASIS,
101 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102 * See the License for the specific language governing permissions and
103 * limitations under the License.
104 *
105 * Author: Tobin Ehlis <tobine@google.com>
106 */"""
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600107
Tobin Ehlis828781a2017-05-23 15:23:40 -0600108 def readJSON(self):
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600109 """Read in JSON file"""
Tobin Ehlis828781a2017-05-23 15:23:40 -0600110 if json_filename is not None:
111 with open(json_filename) as jsf:
Mark Lobodzinski8c9633d2017-06-05 13:50:10 -0600112 self.json_data = json.load(jsf, encoding='utf-8')
Tobin Ehlis828781a2017-05-23 15:23:40 -0600113 else:
Mark Lobodzinski8c9633d2017-06-05 13:50:10 -0600114 response = urllib2.urlopen(json_url).read().decode('utf-8')
115 self.json_data = json.loads(response)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600116
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600117 def parseJSON(self):
118 """Parse JSON VUIDs into data struct"""
119 # Format of JSON file is:
120 # "API": { "core|EXT": [ {"vuid": "<id>", "text": "<VU txt>"}]},
121 # "VK_KHX_external_memory" & "VK_KHX_device_group" - extension case (vs. "core")
Tobin Ehlis798c1392017-06-05 13:23:44 -0600122 for top_level in sorted(self.json_data):
123 if "validation" == top_level:
124 for api in sorted(self.json_data[top_level]):
125 for ext in sorted(self.json_data[top_level][api]):
126 for vu_txt_dict in self.json_data[top_level][api][ext]:
127 print ("Looking at dict for api:ext entry %s:%s" % (api, ext))
128 vuid = vu_txt_dict['vuid']
129 vutxt = vu_txt_dict['text']
130 #print ("%s:%s:%s:%s" % (api, ext, vuid, vutxt))
131 #print ("VUTXT orig:%s" % (vutxt))
132 just_txt = BeautifulSoup(vutxt, 'html.parser')
133 #print ("VUTXT only:%s" % (just_txt.get_text()))
134 num_vuid = vuid_mapping.convertVUID(vuid)
135 self.json_db[vuid] = {}
136 self.json_db[vuid]['ext'] = ext
137 self.json_db[vuid]['number_vuid'] = num_vuid
138 self.json_db[vuid]['struct_func'] = api
139 just_txt = just_txt.get_text().strip()
140 unicode_map = {
141 u"\u2019" : "'",
142 u"\u2192" : "->",
143 }
144 for um in unicode_map:
145 just_txt = just_txt.replace(um, unicode_map[um])
146 self.json_db[vuid]['vu_txt'] = just_txt.replace("\\", "")
147 print ("Spec vu txt:%s" % (self.json_db[vuid]['vu_txt']))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600148 #sys.exit()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600149
150 def compareJSON(self):
151 """Compare parsed json file with existing data read in from DB file"""
Tobin Ehlis828781a2017-05-23 15:23:40 -0600152 json_db_set = set()
153 for vuid in self.json_db: # pull entries out and see which fields we're missing from error_db
154 json_db_set.add(vuid)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600155 for enum in self.error_db_dict:
Tobin Ehlis828781a2017-05-23 15:23:40 -0600156 vuid_string = self.error_db_dict[enum]['vuid_string']
157 if vuid_string not in self.json_db:
158 #print ("Full string for %s is:%s" % (enum, full_error_string))
159 print ("WARN: Couldn't find vuid_string in json db:%s" % (vuid_string))
Tobin Ehlis2c932132017-05-19 16:32:15 -0600160 self.json_missing = self.json_missing + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600161 self.error_db_dict[enum]['ext'] = 'core'
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600162 # TODO: Currently GL843 tracks 2 VUs that are missing from json incorrectly
163 # Fix will land in 1.0.51 spec. After that we should take some alternative
164 # action here to indicate that VUs have gone away.
165 # Can have a removed_enums set that we add to and report to user
Tobin Ehlis828781a2017-05-23 15:23:40 -0600166 #sys.exit()
167 else:
168 json_db_set.remove(vuid_string)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600169 self.error_db_dict[enum]['ext'] = self.json_db[vuid_string]['ext']
170 if 'core' == self.json_db[vuid_string]['ext'] or '!' in self.json_db[vuid_string]['ext']:
171 spec_link = "%s#%s" % (core_url, vuid_string)
172 else:
173 spec_link = "%s#%s" % (ext_url, vuid_string)
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600174 self.error_db_dict[enum]['error_msg'] = "%s'%s' (%s)" % (error_msg_prefix, self.json_db[vuid_string]['vu_txt'], spec_link)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600175 print ("Updated error_db error_msg:%s" % (self.error_db_dict[enum]['error_msg']))
176 #sys.exit()
177 print ("These json DB entries are not in error DB:")
178 for extra_vuid in json_db_set:
179 print ("\t%s" % (extra_vuid))
180 # Add these missing entries into the error_db
181 # Create link into core or ext spec as needed
182 if 'core' == self.json_db[extra_vuid]['ext'] or '!' in self.json_db[extra_vuid]['ext']:
183 spec_link = "%s#%s" % (core_url, extra_vuid)
184 else:
185 spec_link = "%s#%s" % (ext_url, extra_vuid)
Tobin Ehlis798c1392017-06-05 13:23:44 -0600186 error_enum = "%s%s" % (validation_error_enum_name, get8digithex(self.json_db[extra_vuid]['number_vuid']))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600187 self.error_db_dict[error_enum] = {}
188 self.error_db_dict[error_enum]['check_implemented'] = 'N'
189 self.error_db_dict[error_enum]['testname'] = 'None'
190 self.error_db_dict[error_enum]['api'] = self.json_db[extra_vuid]['struct_func']
191 self.error_db_dict[error_enum]['vuid_string'] = extra_vuid
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600192 self.error_db_dict[error_enum]['error_msg'] = "%s'%s' (%s)" % (error_msg_prefix, self.json_db[extra_vuid]['vu_txt'], spec_link)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600193 self.error_db_dict[error_enum]['note'] = ''
194 self.error_db_dict[error_enum]['ext'] = self.json_db[extra_vuid]['ext']
Tobin Ehlis798c1392017-06-05 13:23:44 -0600195 implicit = False
196 last_segment = extra_vuid.split("-")[-1]
197 if last_segment in vuid_mapping.implicit_type_map:
198 implicit = True
199 elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
200 print ("ERROR: Found last segment of val error ID that isn't in implicit map and doesn't have numbers in last segment: %s" % (last_segment))
201 sys.exit()
202 self.error_db_dict[error_enum]['implicit'] = implicit
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600203
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600204 def genHeader(self, header_file):
205 """Generate a header file based on the contents of a parsed spec"""
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600206 print ("Generating header %s..." % (header_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600207 file_contents = []
208 file_contents.append(self.copyright)
209 file_contents.append('\n#pragma once')
Mark Lobodzinski267a7cf2017-01-25 09:33:25 -0700210 file_contents.append('\n// Disable auto-formatting for generated file')
211 file_contents.append('// clang-format off')
212 file_contents.append('\n#include <unordered_map>')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600213 file_contents.append('\n// enum values for unique validation error codes')
214 file_contents.append('// Corresponding validation error message for each enum is given in the mapping table below')
215 file_contents.append('// When a given error occurs, these enum values should be passed to the as the messageCode')
216 file_contents.append('// parameter to the PFN_vkDebugReportCallbackEXT function')
Tobin Ehlis387fd632016-12-08 13:32:05 -0700217 enum_decl = ['enum UNIQUE_VALIDATION_ERROR_CODE {\n VALIDATION_ERROR_UNDEFINED = -1,']
Tobin Ehlisbf98b692016-10-06 12:58:06 -0600218 error_string_map = ['static std::unordered_map<int, char const *const> validation_error_map{']
Tobin Ehlisce1e56f2017-01-25 12:42:55 -0800219 enum_value = 0
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600220 max_enum_val = 0
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600221 for enum in sorted(self.error_db_dict):
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600222 #print ("Header enum is %s" % (enum))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600223 # TMP: Use updated value
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600224 vuid_str = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600225 if vuid_str in self.json_db:
226 enum_value = self.json_db[vuid_str]['number_vuid']
227 else:
228 enum_value = vuid_mapping.convertVUID(vuid_str)
229 new_enum = "%s%s" % (validation_error_enum_name, get8digithex(enum_value))
230 enum_decl.append(' %s = 0x%s,' % (new_enum, get8digithex(enum_value)))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600231 error_string_map.append(' {%s, "%s"},' % (new_enum, self.error_db_dict[enum]['error_msg']))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600232 max_enum_val = max(max_enum_val, enum_value)
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600233 enum_decl.append(' %sMAX_ENUM = %d,' % (validation_error_enum_name, max_enum_val + 1))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600234 enum_decl.append('};')
Tobin Ehlise7560e72016-10-19 15:59:38 -0600235 error_string_map.append('};\n')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600236 file_contents.extend(enum_decl)
237 file_contents.append('\n// Mapping from unique validation error enum to the corresponding error message')
238 file_contents.append('// The error message should be appended to the end of a custom error message that is passed')
239 file_contents.append('// as the pMessage parameter to the PFN_vkDebugReportCallbackEXT function')
240 file_contents.extend(error_string_map)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600241 #print ("File contents: %s" % (file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600242 with open(header_file, "w") as outfile:
243 outfile.write("\n".join(file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600244 def genDB(self, db_file):
Tobin Ehlis828781a2017-05-23 15:23:40 -0600245 """Generate a database of check_enum, check_coded?, testname, API, VUID_string, core|ext, error_string, notes"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600246 db_lines = []
247 # Write header for database file
248 db_lines.append("# This is a database file with validation error check information")
249 db_lines.append("# Comments are denoted with '#' char")
250 db_lines.append("# The format of the lines is:")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600251 db_lines.append("# <error_enum>%s<check_implemented>%s<testname>%s<api>%s<vuid_string>%s<core|ext>%s<errormsg>%s<note>" % (self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter, self.delimiter))
Mark Lobodzinski629d47b2016-10-18 13:34:58 -0600252 db_lines.append("# error_enum: Unique error enum for this check of format %s<uniqueid>" % validation_error_enum_name)
Mike Weiblenfe186122017-02-03 12:44:53 -0700253 db_lines.append("# check_implemented: 'Y' if check has been implemented in layers, or 'N' for not implemented")
Dave Houlton14f7e662017-05-17 13:25:53 -0600254 db_lines.append("# testname: Name of validation test for this check, 'Unknown' for unknown, 'None' if not implemented, or 'NotTestable' if cannot be implemented")
Tobin Ehlise7560e72016-10-19 15:59:38 -0600255 db_lines.append("# api: Vulkan API function that this check is related to")
Tobin Ehlis2c932132017-05-19 16:32:15 -0600256 db_lines.append("# vuid_string: Unique string to identify this check")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600257 db_lines.append("# core|ext: Either 'core' for core spec or some extension string that indicates the extension required for this VU to be relevant")
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600258 db_lines.append("# errormsg: The unique error message for this check that includes spec language and link")
Tobin Ehlise7560e72016-10-19 15:59:38 -0600259 db_lines.append("# note: Free txt field with any custom notes related to the check in question")
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600260 for enum in sorted(self.error_db_dict):
Tobin Ehlis798c1392017-06-05 13:23:44 -0600261 print ("Gen DB for enum %s" % (enum))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600262 implicit = self.error_db_dict[enum]['implicit']
263 implemented = self.error_db_dict[enum]['check_implemented']
264 testname = self.error_db_dict[enum]['testname']
265 note = self.error_db_dict[enum]['note']
266 core_ext = self.error_db_dict[enum]['ext']
267 self.error_db_dict[enum]['vuid_string'] = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis2a176b12017-01-11 16:18:20 -0700268 if implicit and 'implicit' not in note: # add implicit note
269 if '' != note:
270 note = "implicit, %s" % (note)
271 else:
272 note = "implicit"
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600273 db_lines.append("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s" % (enum, self.delimiter, implemented, self.delimiter, testname, self.delimiter, self.error_db_dict[enum]['api'], self.delimiter, self.error_db_dict[enum]['vuid_string'], self.delimiter, core_ext, self.delimiter, self.error_db_dict[enum]['error_msg'], self.delimiter, note))
Tobin Ehlisaf75f7c2016-10-31 11:10:38 -0600274 db_lines.append("\n") # newline at end of file
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600275 print ("Generating database file %s" % (db_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600276 with open(db_file, "w") as outfile:
277 outfile.write("\n".join(db_lines))
278 def readDB(self, db_file):
Tobin Ehlis2c932132017-05-19 16:32:15 -0600279 """Read a db file into a dict, refer to genDB function above for format of each line"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600280 with open(db_file, "r") as infile:
281 for line in infile:
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600282 line = line.strip()
Tobin Ehlisf4245cb2016-10-31 07:55:19 -0600283 if line.startswith('#') or '' == line:
284 continue
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600285 db_line = line.split(self.delimiter)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600286 if len(db_line) != 8:
287 print ("ERROR: Bad database line doesn't have 8 elements: %s" % (line))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600288 error_enum = db_line[0]
289 implemented = db_line[1]
290 testname = db_line[2]
Tobin Ehlis70980c02016-10-25 14:00:20 -0600291 api = db_line[3]
Tobin Ehlis828781a2017-05-23 15:23:40 -0600292 vuid_str = db_line[4]
293 core_ext = db_line[5]
294 error_str = db_line[6]
295 note = db_line[7]
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600296 # Also read complete database contents into our class var for later use
297 self.error_db_dict[error_enum] = {}
298 self.error_db_dict[error_enum]['check_implemented'] = implemented
299 self.error_db_dict[error_enum]['testname'] = testname
Tobin Ehlis70980c02016-10-25 14:00:20 -0600300 self.error_db_dict[error_enum]['api'] = api
Tobin Ehlis828781a2017-05-23 15:23:40 -0600301 self.error_db_dict[error_enum]['vuid_string'] = vuid_str
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600302 self.error_db_dict[error_enum]['ext'] = core_ext
Tobin Ehlis828781a2017-05-23 15:23:40 -0600303 self.error_db_dict[error_enum]['error_msg'] = error_str
Tobin Ehlis70980c02016-10-25 14:00:20 -0600304 self.error_db_dict[error_enum]['note'] = note
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600305 implicit = False
306 last_segment = vuid_str.split("-")[-1]
307 if last_segment in vuid_mapping.implicit_type_map:
308 implicit = True
309 elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
Tobin Ehlis798c1392017-06-05 13:23:44 -0600310 print ("ERROR: Found last segment of val error ID that isn't in implicit map and doesn't have numbers in last segment: %s" % (last_segment))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600311 sys.exit()
312 self.error_db_dict[error_enum]['implicit'] = implicit
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600313if __name__ == "__main__":
314 i = 1
315 use_online = True # Attempt to grab spec from online by default
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600316 while (i < len(sys.argv)):
317 arg = sys.argv[i]
318 i = i + 1
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600319 if (arg == '-json-file'):
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600320 json_filename = sys.argv[i]
321 i = i + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600322 elif (arg == '-json'):
323 read_json = True
Tobin Ehlis2c932132017-05-19 16:32:15 -0600324 elif (arg == '-json-compare'):
325 json_compare = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600326 elif (arg == '-out'):
327 out_filename = sys.argv[i]
328 i = i + 1
329 elif (arg == '-gendb'):
330 gen_db = True
331 # Set filename if supplied, else use default
332 if i < len(sys.argv) and not sys.argv[i].startswith('-'):
333 db_filename = sys.argv[i]
334 i = i + 1
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600335 elif (arg == '-update'):
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600336 read_json = True
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600337 json_compare = True
338 gen_db = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600339 elif (arg in ['-help', '-h']):
340 printHelp()
341 sys.exit()
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600342 spec = Specification()
Tobin Ehlis828781a2017-05-23 15:23:40 -0600343 if read_json:
344 spec.readJSON()
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600345 spec.parseJSON()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600346 #sys.exit()
347 if (json_compare):
348 # Read in current spec info from db file
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600349 (orig_err_msg_dict) = spec.readDB(db_filename)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600350 spec.compareJSON()
351 print ("Found %d missing db entries in json db" % (spec.json_missing))
352 print ("Found %d duplicate json entries" % (spec.duplicate_json_key_count))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600353 spec.genDB(db_filename)
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600354 if (gen_db):
355 spec.genDB(db_filename)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600356 print ("Writing out file (-out) to '%s'" % (out_filename))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600357 spec.genHeader(out_filename)