blob: 4304446692a0bc6739fe068984812d52d5097159 [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
Tobin Ehlis5ade0692016-10-05 17:18:15 -06004import urllib2
Tobin Ehlis3198ba32017-04-19 17:30:52 -06005from bs4 import BeautifulSoup
Tobin Ehlis98d109a2017-05-11 14:42:38 -06006import json
7import vuid_mapping
Tobin Ehlis5ade0692016-10-05 17:18:15 -06008
9#############################
10# spec.py script
11#
Tobin Ehlisda3916c2017-05-24 14:13:46 -060012# Overview - this script is intended to generate validation error codes and message strings from the json spec file
13# that contains all of the valid usage statements. In addition to generating the header file, it provides a number of
14# corrollary services to aid in generating/updating the header.
Tobin Ehlis5ade0692016-10-05 17:18:15 -060015#
Tobin Ehlisda3916c2017-05-24 14:13:46 -060016# Ideal flow - Pull the valid usage text and IDs from the spec json, pull the IDs from the validation error database,
17# 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 -060018#
19# TODO:
Tobin Ehlisda3916c2017-05-24 14:13:46 -060020# 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 -060021#
22#############################
23
24
Tobin Ehlis5ade0692016-10-05 17:18:15 -060025out_filename = "vk_validation_error_messages.h" # can override w/ '-out <filename>' option
26db_filename = "vk_validation_error_database.txt" # can override w/ '-gendb <filename>' option
Tobin Ehlis2c932132017-05-19 16:32:15 -060027json_filename = None # con pass in w/ '-json <filename> option
Tobin Ehlis5ade0692016-10-05 17:18:15 -060028gen_db = False # set to True when '-gendb <filename>' option provided
Tobin Ehlis2c932132017-05-19 16:32:15 -060029json_compare = False # compare existing DB to json file input
Tobin Ehlis828781a2017-05-23 15:23:40 -060030json_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/validation/validusage.json"
31read_json = False
Tobin Ehlis5ade0692016-10-05 17:18:15 -060032# 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 -060033#old_spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0/xhtml/vkspec.html"
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060034spec_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
Tobin Ehlis828781a2017-05-23 15:23:40 -060035core_url = "https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html"
36ext_url = "https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html"
Tobin Ehlis5ade0692016-10-05 17:18:15 -060037# After the custom validation error message, this is the prefix for the standard message that includes the
38# spec valid usage language as well as the link to nearest section of spec to that language
Tobin Ehlisda3916c2017-05-24 14:13:46 -060039error_msg_prefix = "The spec valid usage text states "
Mark Lobodzinski629d47b2016-10-18 13:34:58 -060040validation_error_enum_name = "VALIDATION_ERROR_"
Tobin Ehlis5ade0692016-10-05 17:18:15 -060041
42def printHelp():
Tobin Ehlisda3916c2017-05-24 14:13:46 -060043 print ("Usage: python spec.py [-out <headerfile.h>] [-gendb <databasefile.txt>] [-update] [-json <json_file>] [-help]")
Tobin Ehlis3198ba32017-04-19 17:30:52 -060044 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")
45 print (" Default specfile is from online at %s" % (spec_url))
46 print (" Default headerfile is %s" % (out_filename))
47 print (" Default databasefile is %s" % (db_filename))
48 print ("\nIf '-gendb' option is specified then a database file is generated to default file or <databasefile.txt> if supplied. The database file stores")
49 print (" the list of enums and their error messages.")
Tobin Ehlis3198ba32017-04-19 17:30:52 -060050 print ("\nIf '-update' option is specified this triggers the master flow to automate updating header and database files using default db file as baseline")
51 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 -060052 print ("\nIf '-json' option is used trigger the script to load in data from a json file.")
53 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 -060054
Tobin Ehlis3c37fb32017-05-24 09:31:13 -060055def get8digithex(dec_num):
56 """Convert a decimal # into an 8-digit hex"""
57 if dec_num > 4294967295:
58 print ("ERROR: Decimal # %d can't be represented in 8 hex digits" % (dec_num))
59 sys.exit()
60 hex_num = hex(dec_num)
61 return hex_num[2:].zfill(8)
62
Tobin Ehlis5ade0692016-10-05 17:18:15 -060063class Specification:
64 def __init__(self):
65 self.tree = None
Tobin Ehlis5ade0692016-10-05 17:18:15 -060066 self.error_db_dict = {} # dict of previous error values read in from database file
67 self.delimiter = '~^~' # delimiter for db file
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060068 # Global dicts used for tracking spec updates from old to new VUs
Tobin Ehlisa55b1d42017-04-04 12:23:48 -060069 self.orig_no_link_msg_dict = {} # Pair of API,Original msg w/o spec link to ID list mapping
70 self.orig_core_msg_dict = {} # Pair of API,Original core msg (no link or section) to ID list mapping
71 self.last_mapped_id = -10 # start as negative so we don't hit an accidental sequence
72 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 -060073 # Dict of data from json DB
74 # Key is API,<short_msg> which leads to dict w/ following values
75 # 'ext' -> <core|<ext_name>>
76 # 'string_vuid' -> <string_vuid>
77 # 'number_vuid' -> <numerical_vuid>
78 self.json_db = {}
79 self.json_missing = 0
80 self.struct_to_func_map = {} # Map structs to the API func that they fall under in the spec
81 self.duplicate_json_key_count = 0
Tobin Ehlis5ade0692016-10-05 17:18:15 -060082 self.copyright = """/* THIS FILE IS GENERATED. DO NOT EDIT. */
83
84/*
85 * Vulkan
86 *
87 * Copyright (c) 2016 Google Inc.
Mark Lobodzinski629d47b2016-10-18 13:34:58 -060088 * Copyright (c) 2016 LunarG, Inc.
Tobin Ehlis5ade0692016-10-05 17:18:15 -060089 *
90 * Licensed under the Apache License, Version 2.0 (the "License");
91 * you may not use this file except in compliance with the License.
92 * You may obtain a copy of the License at
93 *
94 * http://www.apache.org/licenses/LICENSE-2.0
95 *
96 * Unless required by applicable law or agreed to in writing, software
97 * distributed under the License is distributed on an "AS IS" BASIS,
98 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
99 * See the License for the specific language governing permissions and
100 * limitations under the License.
101 *
102 * Author: Tobin Ehlis <tobine@google.com>
103 */"""
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600104
Tobin Ehlis828781a2017-05-23 15:23:40 -0600105 def readJSON(self):
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600106 """Read in JSON file"""
Tobin Ehlis828781a2017-05-23 15:23:40 -0600107 if json_filename is not None:
108 with open(json_filename) as jsf:
109 self.json_data = json.load(jsf)
110 else:
111 self.json_data = json.load(urllib2.urlopen(json_url))
112
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600113 def parseJSON(self):
114 """Parse JSON VUIDs into data struct"""
115 # Format of JSON file is:
116 # "API": { "core|EXT": [ {"vuid": "<id>", "text": "<VU txt>"}]},
117 # "VK_KHX_external_memory" & "VK_KHX_device_group" - extension case (vs. "core")
Tobin Ehlis798c1392017-06-05 13:23:44 -0600118 for top_level in sorted(self.json_data):
119 if "validation" == top_level:
120 for api in sorted(self.json_data[top_level]):
121 for ext in sorted(self.json_data[top_level][api]):
122 for vu_txt_dict in self.json_data[top_level][api][ext]:
123 print ("Looking at dict for api:ext entry %s:%s" % (api, ext))
124 vuid = vu_txt_dict['vuid']
125 vutxt = vu_txt_dict['text']
126 #print ("%s:%s:%s:%s" % (api, ext, vuid, vutxt))
127 #print ("VUTXT orig:%s" % (vutxt))
128 just_txt = BeautifulSoup(vutxt, 'html.parser')
129 #print ("VUTXT only:%s" % (just_txt.get_text()))
130 num_vuid = vuid_mapping.convertVUID(vuid)
131 self.json_db[vuid] = {}
132 self.json_db[vuid]['ext'] = ext
133 self.json_db[vuid]['number_vuid'] = num_vuid
134 self.json_db[vuid]['struct_func'] = api
135 just_txt = just_txt.get_text().strip()
136 unicode_map = {
137 u"\u2019" : "'",
138 u"\u2192" : "->",
139 }
140 for um in unicode_map:
141 just_txt = just_txt.replace(um, unicode_map[um])
142 self.json_db[vuid]['vu_txt'] = just_txt.replace("\\", "")
143 print ("Spec vu txt:%s" % (self.json_db[vuid]['vu_txt']))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600144 #sys.exit()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600145
146 def compareJSON(self):
147 """Compare parsed json file with existing data read in from DB file"""
Tobin Ehlis828781a2017-05-23 15:23:40 -0600148 json_db_set = set()
149 for vuid in self.json_db: # pull entries out and see which fields we're missing from error_db
150 json_db_set.add(vuid)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600151 for enum in self.error_db_dict:
Tobin Ehlis828781a2017-05-23 15:23:40 -0600152 vuid_string = self.error_db_dict[enum]['vuid_string']
153 if vuid_string not in self.json_db:
154 #print ("Full string for %s is:%s" % (enum, full_error_string))
155 print ("WARN: Couldn't find vuid_string in json db:%s" % (vuid_string))
Tobin Ehlis2c932132017-05-19 16:32:15 -0600156 self.json_missing = self.json_missing + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600157 self.error_db_dict[enum]['ext'] = 'core'
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600158 # TODO: Currently GL843 tracks 2 VUs that are missing from json incorrectly
159 # Fix will land in 1.0.51 spec. After that we should take some alternative
160 # action here to indicate that VUs have gone away.
161 # Can have a removed_enums set that we add to and report to user
Tobin Ehlis828781a2017-05-23 15:23:40 -0600162 #sys.exit()
163 else:
164 json_db_set.remove(vuid_string)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600165 self.error_db_dict[enum]['ext'] = self.json_db[vuid_string]['ext']
166 if 'core' == self.json_db[vuid_string]['ext'] or '!' in self.json_db[vuid_string]['ext']:
167 spec_link = "%s#%s" % (core_url, vuid_string)
168 else:
169 spec_link = "%s#%s" % (ext_url, vuid_string)
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600170 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 -0600171 print ("Updated error_db error_msg:%s" % (self.error_db_dict[enum]['error_msg']))
172 #sys.exit()
173 print ("These json DB entries are not in error DB:")
174 for extra_vuid in json_db_set:
175 print ("\t%s" % (extra_vuid))
176 # Add these missing entries into the error_db
177 # Create link into core or ext spec as needed
178 if 'core' == self.json_db[extra_vuid]['ext'] or '!' in self.json_db[extra_vuid]['ext']:
179 spec_link = "%s#%s" % (core_url, extra_vuid)
180 else:
181 spec_link = "%s#%s" % (ext_url, extra_vuid)
Tobin Ehlis798c1392017-06-05 13:23:44 -0600182 error_enum = "%s%s" % (validation_error_enum_name, get8digithex(self.json_db[extra_vuid]['number_vuid']))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600183 self.error_db_dict[error_enum] = {}
184 self.error_db_dict[error_enum]['check_implemented'] = 'N'
185 self.error_db_dict[error_enum]['testname'] = 'None'
186 self.error_db_dict[error_enum]['api'] = self.json_db[extra_vuid]['struct_func']
187 self.error_db_dict[error_enum]['vuid_string'] = extra_vuid
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600188 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 -0600189 self.error_db_dict[error_enum]['note'] = ''
190 self.error_db_dict[error_enum]['ext'] = self.json_db[extra_vuid]['ext']
Tobin Ehlis798c1392017-06-05 13:23:44 -0600191 implicit = False
192 last_segment = extra_vuid.split("-")[-1]
193 if last_segment in vuid_mapping.implicit_type_map:
194 implicit = True
195 elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
196 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))
197 sys.exit()
198 self.error_db_dict[error_enum]['implicit'] = implicit
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600199
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600200 def genHeader(self, header_file):
201 """Generate a header file based on the contents of a parsed spec"""
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600202 print ("Generating header %s..." % (header_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600203 file_contents = []
204 file_contents.append(self.copyright)
205 file_contents.append('\n#pragma once')
Mark Lobodzinski267a7cf2017-01-25 09:33:25 -0700206 file_contents.append('\n// Disable auto-formatting for generated file')
207 file_contents.append('// clang-format off')
208 file_contents.append('\n#include <unordered_map>')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600209 file_contents.append('\n// enum values for unique validation error codes')
210 file_contents.append('// Corresponding validation error message for each enum is given in the mapping table below')
211 file_contents.append('// When a given error occurs, these enum values should be passed to the as the messageCode')
212 file_contents.append('// parameter to the PFN_vkDebugReportCallbackEXT function')
Tobin Ehlis387fd632016-12-08 13:32:05 -0700213 enum_decl = ['enum UNIQUE_VALIDATION_ERROR_CODE {\n VALIDATION_ERROR_UNDEFINED = -1,']
Tobin Ehlisbf98b692016-10-06 12:58:06 -0600214 error_string_map = ['static std::unordered_map<int, char const *const> validation_error_map{']
Tobin Ehlisce1e56f2017-01-25 12:42:55 -0800215 enum_value = 0
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600216 max_enum_val = 0
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600217 for enum in sorted(self.error_db_dict):
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600218 #print ("Header enum is %s" % (enum))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600219 # TMP: Use updated value
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600220 vuid_str = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600221 if vuid_str in self.json_db:
222 enum_value = self.json_db[vuid_str]['number_vuid']
223 else:
224 enum_value = vuid_mapping.convertVUID(vuid_str)
225 new_enum = "%s%s" % (validation_error_enum_name, get8digithex(enum_value))
226 enum_decl.append(' %s = 0x%s,' % (new_enum, get8digithex(enum_value)))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600227 error_string_map.append(' {%s, "%s"},' % (new_enum, self.error_db_dict[enum]['error_msg']))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600228 max_enum_val = max(max_enum_val, enum_value)
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600229 enum_decl.append(' %sMAX_ENUM = %d,' % (validation_error_enum_name, max_enum_val + 1))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600230 enum_decl.append('};')
Tobin Ehlise7560e72016-10-19 15:59:38 -0600231 error_string_map.append('};\n')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600232 file_contents.extend(enum_decl)
233 file_contents.append('\n// Mapping from unique validation error enum to the corresponding error message')
234 file_contents.append('// The error message should be appended to the end of a custom error message that is passed')
235 file_contents.append('// as the pMessage parameter to the PFN_vkDebugReportCallbackEXT function')
236 file_contents.extend(error_string_map)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600237 #print ("File contents: %s" % (file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600238 with open(header_file, "w") as outfile:
239 outfile.write("\n".join(file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600240 def genDB(self, db_file):
Tobin Ehlis828781a2017-05-23 15:23:40 -0600241 """Generate a database of check_enum, check_coded?, testname, API, VUID_string, core|ext, error_string, notes"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600242 db_lines = []
243 # Write header for database file
244 db_lines.append("# This is a database file with validation error check information")
245 db_lines.append("# Comments are denoted with '#' char")
246 db_lines.append("# The format of the lines is:")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600247 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 -0600248 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 -0700249 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 -0600250 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 -0600251 db_lines.append("# api: Vulkan API function that this check is related to")
Tobin Ehlis2c932132017-05-19 16:32:15 -0600252 db_lines.append("# vuid_string: Unique string to identify this check")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600253 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 -0600254 db_lines.append("# errormsg: The unique error message for this check that includes spec language and link")
Tobin Ehlise7560e72016-10-19 15:59:38 -0600255 db_lines.append("# note: Free txt field with any custom notes related to the check in question")
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600256 for enum in sorted(self.error_db_dict):
Tobin Ehlis798c1392017-06-05 13:23:44 -0600257 print ("Gen DB for enum %s" % (enum))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600258 implicit = self.error_db_dict[enum]['implicit']
259 implemented = self.error_db_dict[enum]['check_implemented']
260 testname = self.error_db_dict[enum]['testname']
261 note = self.error_db_dict[enum]['note']
262 core_ext = self.error_db_dict[enum]['ext']
263 self.error_db_dict[enum]['vuid_string'] = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis2a176b12017-01-11 16:18:20 -0700264 if implicit and 'implicit' not in note: # add implicit note
265 if '' != note:
266 note = "implicit, %s" % (note)
267 else:
268 note = "implicit"
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600269 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 -0600270 db_lines.append("\n") # newline at end of file
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600271 print ("Generating database file %s" % (db_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600272 with open(db_file, "w") as outfile:
273 outfile.write("\n".join(db_lines))
274 def readDB(self, db_file):
Tobin Ehlis2c932132017-05-19 16:32:15 -0600275 """Read a db file into a dict, refer to genDB function above for format of each line"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600276 with open(db_file, "r") as infile:
277 for line in infile:
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600278 line = line.strip()
Tobin Ehlisf4245cb2016-10-31 07:55:19 -0600279 if line.startswith('#') or '' == line:
280 continue
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600281 db_line = line.split(self.delimiter)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600282 if len(db_line) != 8:
283 print ("ERROR: Bad database line doesn't have 8 elements: %s" % (line))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600284 error_enum = db_line[0]
285 implemented = db_line[1]
286 testname = db_line[2]
Tobin Ehlis70980c02016-10-25 14:00:20 -0600287 api = db_line[3]
Tobin Ehlis828781a2017-05-23 15:23:40 -0600288 vuid_str = db_line[4]
289 core_ext = db_line[5]
290 error_str = db_line[6]
291 note = db_line[7]
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600292 # Also read complete database contents into our class var for later use
293 self.error_db_dict[error_enum] = {}
294 self.error_db_dict[error_enum]['check_implemented'] = implemented
295 self.error_db_dict[error_enum]['testname'] = testname
Tobin Ehlis70980c02016-10-25 14:00:20 -0600296 self.error_db_dict[error_enum]['api'] = api
Tobin Ehlis828781a2017-05-23 15:23:40 -0600297 self.error_db_dict[error_enum]['vuid_string'] = vuid_str
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600298 self.error_db_dict[error_enum]['ext'] = core_ext
Tobin Ehlis828781a2017-05-23 15:23:40 -0600299 self.error_db_dict[error_enum]['error_msg'] = error_str
Tobin Ehlis70980c02016-10-25 14:00:20 -0600300 self.error_db_dict[error_enum]['note'] = note
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600301 implicit = False
302 last_segment = vuid_str.split("-")[-1]
303 if last_segment in vuid_mapping.implicit_type_map:
304 implicit = True
305 elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
Tobin Ehlis798c1392017-06-05 13:23:44 -0600306 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 -0600307 sys.exit()
308 self.error_db_dict[error_enum]['implicit'] = implicit
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600309if __name__ == "__main__":
310 i = 1
311 use_online = True # Attempt to grab spec from online by default
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600312 while (i < len(sys.argv)):
313 arg = sys.argv[i]
314 i = i + 1
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600315 if (arg == '-json-file'):
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600316 json_filename = sys.argv[i]
317 i = i + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600318 elif (arg == '-json'):
319 read_json = True
Tobin Ehlis2c932132017-05-19 16:32:15 -0600320 elif (arg == '-json-compare'):
321 json_compare = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600322 elif (arg == '-out'):
323 out_filename = sys.argv[i]
324 i = i + 1
325 elif (arg == '-gendb'):
326 gen_db = True
327 # Set filename if supplied, else use default
328 if i < len(sys.argv) and not sys.argv[i].startswith('-'):
329 db_filename = sys.argv[i]
330 i = i + 1
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600331 elif (arg == '-update'):
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600332 read_json = True
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600333 json_compare = True
334 gen_db = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600335 elif (arg in ['-help', '-h']):
336 printHelp()
337 sys.exit()
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600338 spec = Specification()
Tobin Ehlis828781a2017-05-23 15:23:40 -0600339 if read_json:
340 spec.readJSON()
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600341 spec.parseJSON()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600342 #sys.exit()
343 if (json_compare):
344 # Read in current spec info from db file
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600345 (orig_err_msg_dict) = spec.readDB(db_filename)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600346 spec.compareJSON()
347 print ("Found %d missing db entries in json db" % (spec.json_missing))
348 print ("Found %d duplicate json entries" % (spec.duplicate_json_key_count))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600349 spec.genDB(db_filename)
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600350 if (gen_db):
351 spec.genDB(db_filename)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600352 print ("Writing out file (-out) to '%s'" % (out_filename))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600353 spec.genHeader(out_filename)