blob: b65f9ffc65203c09431910a74dd4e56b6d0724d2 [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 Ehlis98d109a2017-05-11 14:42:38 -0600118 for api in sorted(self.json_data):
119 for ext in sorted(self.json_data[api]):
120 for vu_txt_dict in self.json_data[api][ext]:
121 vuid = vu_txt_dict['vuid']
122 vutxt = vu_txt_dict['text']
123 #print ("%s:%s:%s:%s" % (api, ext, vuid, vutxt))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600124 #print ("VUTXT orig:%s" % (vutxt))
Tobin Ehlis2c932132017-05-19 16:32:15 -0600125 just_txt = BeautifulSoup(vutxt, 'html.parser')
126 #print ("VUTXT only:%s" % (just_txt.get_text()))
127 num_vuid = vuid_mapping.convertVUID(vuid)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600128 self.json_db[vuid] = {}
129 self.json_db[vuid]['ext'] = ext
Tobin Ehlis828781a2017-05-23 15:23:40 -0600130 self.json_db[vuid]['number_vuid'] = num_vuid
131 self.json_db[vuid]['struct_func'] = api
132 just_txt = just_txt.get_text().strip()
133 unicode_map = {
134 u"\u2019" : "'",
135 u"\u2192" : "->",
136 }
137 for um in unicode_map:
138 just_txt = just_txt.replace(um, unicode_map[um])
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600139 self.json_db[vuid]['vu_txt'] = just_txt.replace("\\", "")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600140 print ("Spec vu txt:%s" % (self.json_db[vuid]['vu_txt']))
Tobin Ehlis828781a2017-05-23 15:23:40 -0600141 #sys.exit()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600142
143 def compareJSON(self):
144 """Compare parsed json file with existing data read in from DB file"""
Tobin Ehlis828781a2017-05-23 15:23:40 -0600145 json_db_set = set()
146 for vuid in self.json_db: # pull entries out and see which fields we're missing from error_db
147 json_db_set.add(vuid)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600148 for enum in self.error_db_dict:
Tobin Ehlis828781a2017-05-23 15:23:40 -0600149 vuid_string = self.error_db_dict[enum]['vuid_string']
150 if vuid_string not in self.json_db:
151 #print ("Full string for %s is:%s" % (enum, full_error_string))
152 print ("WARN: Couldn't find vuid_string in json db:%s" % (vuid_string))
Tobin Ehlis2c932132017-05-19 16:32:15 -0600153 self.json_missing = self.json_missing + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600154 self.error_db_dict[enum]['ext'] = 'core'
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600155 # TODO: Currently GL843 tracks 2 VUs that are missing from json incorrectly
156 # Fix will land in 1.0.51 spec. After that we should take some alternative
157 # action here to indicate that VUs have gone away.
158 # Can have a removed_enums set that we add to and report to user
Tobin Ehlis828781a2017-05-23 15:23:40 -0600159 #sys.exit()
160 else:
161 json_db_set.remove(vuid_string)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600162 self.error_db_dict[enum]['ext'] = self.json_db[vuid_string]['ext']
163 if 'core' == self.json_db[vuid_string]['ext'] or '!' in self.json_db[vuid_string]['ext']:
164 spec_link = "%s#%s" % (core_url, vuid_string)
165 else:
166 spec_link = "%s#%s" % (ext_url, vuid_string)
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600167 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 -0600168 print ("Updated error_db error_msg:%s" % (self.error_db_dict[enum]['error_msg']))
169 #sys.exit()
170 print ("These json DB entries are not in error DB:")
171 for extra_vuid in json_db_set:
172 print ("\t%s" % (extra_vuid))
173 # Add these missing entries into the error_db
174 # Create link into core or ext spec as needed
175 if 'core' == self.json_db[extra_vuid]['ext'] or '!' in self.json_db[extra_vuid]['ext']:
176 spec_link = "%s#%s" % (core_url, extra_vuid)
177 else:
178 spec_link = "%s#%s" % (ext_url, extra_vuid)
179 error_enum = "VALIDATION_ERROR_%d" % (self.json_db[extra_vuid]['number_vuid'])
180 self.error_db_dict[error_enum] = {}
181 self.error_db_dict[error_enum]['check_implemented'] = 'N'
182 self.error_db_dict[error_enum]['testname'] = 'None'
183 self.error_db_dict[error_enum]['api'] = self.json_db[extra_vuid]['struct_func']
184 self.error_db_dict[error_enum]['vuid_string'] = extra_vuid
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600185 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 -0600186 self.error_db_dict[error_enum]['note'] = ''
187 self.error_db_dict[error_enum]['ext'] = self.json_db[extra_vuid]['ext']
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600188
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600189 def genHeader(self, header_file):
190 """Generate a header file based on the contents of a parsed spec"""
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600191 print ("Generating header %s..." % (header_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600192 file_contents = []
193 file_contents.append(self.copyright)
194 file_contents.append('\n#pragma once')
Mark Lobodzinski267a7cf2017-01-25 09:33:25 -0700195 file_contents.append('\n// Disable auto-formatting for generated file')
196 file_contents.append('// clang-format off')
197 file_contents.append('\n#include <unordered_map>')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600198 file_contents.append('\n// enum values for unique validation error codes')
199 file_contents.append('// Corresponding validation error message for each enum is given in the mapping table below')
200 file_contents.append('// When a given error occurs, these enum values should be passed to the as the messageCode')
201 file_contents.append('// parameter to the PFN_vkDebugReportCallbackEXT function')
Tobin Ehlis387fd632016-12-08 13:32:05 -0700202 enum_decl = ['enum UNIQUE_VALIDATION_ERROR_CODE {\n VALIDATION_ERROR_UNDEFINED = -1,']
Tobin Ehlisbf98b692016-10-06 12:58:06 -0600203 error_string_map = ['static std::unordered_map<int, char const *const> validation_error_map{']
Tobin Ehlisce1e56f2017-01-25 12:42:55 -0800204 enum_value = 0
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600205 max_enum_val = 0
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600206 for enum in sorted(self.error_db_dict):
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600207 #print ("Header enum is %s" % (enum))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600208 # TMP: Use updated value
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600209 vuid_str = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600210 if vuid_str in self.json_db:
211 enum_value = self.json_db[vuid_str]['number_vuid']
212 else:
213 enum_value = vuid_mapping.convertVUID(vuid_str)
214 new_enum = "%s%s" % (validation_error_enum_name, get8digithex(enum_value))
215 enum_decl.append(' %s = 0x%s,' % (new_enum, get8digithex(enum_value)))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600216 error_string_map.append(' {%s, "%s"},' % (new_enum, self.error_db_dict[enum]['error_msg']))
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600217 max_enum_val = max(max_enum_val, enum_value)
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600218 enum_decl.append(' %sMAX_ENUM = %d,' % (validation_error_enum_name, max_enum_val + 1))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600219 enum_decl.append('};')
Tobin Ehlise7560e72016-10-19 15:59:38 -0600220 error_string_map.append('};\n')
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600221 file_contents.extend(enum_decl)
222 file_contents.append('\n// Mapping from unique validation error enum to the corresponding error message')
223 file_contents.append('// The error message should be appended to the end of a custom error message that is passed')
224 file_contents.append('// as the pMessage parameter to the PFN_vkDebugReportCallbackEXT function')
225 file_contents.extend(error_string_map)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600226 #print ("File contents: %s" % (file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600227 with open(header_file, "w") as outfile:
228 outfile.write("\n".join(file_contents))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600229 def genDB(self, db_file):
Tobin Ehlis828781a2017-05-23 15:23:40 -0600230 """Generate a database of check_enum, check_coded?, testname, API, VUID_string, core|ext, error_string, notes"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600231 db_lines = []
232 # Write header for database file
233 db_lines.append("# This is a database file with validation error check information")
234 db_lines.append("# Comments are denoted with '#' char")
235 db_lines.append("# The format of the lines is:")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600236 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 -0600237 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 -0700238 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 -0600239 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 -0600240 db_lines.append("# api: Vulkan API function that this check is related to")
Tobin Ehlis2c932132017-05-19 16:32:15 -0600241 db_lines.append("# vuid_string: Unique string to identify this check")
Tobin Ehlis828781a2017-05-23 15:23:40 -0600242 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 -0600243 db_lines.append("# errormsg: The unique error message for this check that includes spec language and link")
Tobin Ehlise7560e72016-10-19 15:59:38 -0600244 db_lines.append("# note: Free txt field with any custom notes related to the check in question")
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600245 for enum in sorted(self.error_db_dict):
246 implicit = self.error_db_dict[enum]['implicit']
247 implemented = self.error_db_dict[enum]['check_implemented']
248 testname = self.error_db_dict[enum]['testname']
249 note = self.error_db_dict[enum]['note']
250 core_ext = self.error_db_dict[enum]['ext']
251 self.error_db_dict[enum]['vuid_string'] = self.error_db_dict[enum]['vuid_string']
Tobin Ehlis2a176b12017-01-11 16:18:20 -0700252 if implicit and 'implicit' not in note: # add implicit note
253 if '' != note:
254 note = "implicit, %s" % (note)
255 else:
256 note = "implicit"
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600257 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 -0600258 db_lines.append("\n") # newline at end of file
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600259 print ("Generating database file %s" % (db_file))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600260 with open(db_file, "w") as outfile:
261 outfile.write("\n".join(db_lines))
262 def readDB(self, db_file):
Tobin Ehlis2c932132017-05-19 16:32:15 -0600263 """Read a db file into a dict, refer to genDB function above for format of each line"""
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600264 with open(db_file, "r") as infile:
265 for line in infile:
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600266 line = line.strip()
Tobin Ehlisf4245cb2016-10-31 07:55:19 -0600267 if line.startswith('#') or '' == line:
268 continue
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600269 db_line = line.split(self.delimiter)
Tobin Ehlis828781a2017-05-23 15:23:40 -0600270 if len(db_line) != 8:
271 print ("ERROR: Bad database line doesn't have 8 elements: %s" % (line))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600272 error_enum = db_line[0]
273 implemented = db_line[1]
274 testname = db_line[2]
Tobin Ehlis70980c02016-10-25 14:00:20 -0600275 api = db_line[3]
Tobin Ehlis828781a2017-05-23 15:23:40 -0600276 vuid_str = db_line[4]
277 core_ext = db_line[5]
278 error_str = db_line[6]
279 note = db_line[7]
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600280 # Also read complete database contents into our class var for later use
281 self.error_db_dict[error_enum] = {}
282 self.error_db_dict[error_enum]['check_implemented'] = implemented
283 self.error_db_dict[error_enum]['testname'] = testname
Tobin Ehlis70980c02016-10-25 14:00:20 -0600284 self.error_db_dict[error_enum]['api'] = api
Tobin Ehlis828781a2017-05-23 15:23:40 -0600285 self.error_db_dict[error_enum]['vuid_string'] = vuid_str
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600286 self.error_db_dict[error_enum]['ext'] = core_ext
Tobin Ehlis828781a2017-05-23 15:23:40 -0600287 self.error_db_dict[error_enum]['error_msg'] = error_str
Tobin Ehlis70980c02016-10-25 14:00:20 -0600288 self.error_db_dict[error_enum]['note'] = note
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600289 implicit = False
290 last_segment = vuid_str.split("-")[-1]
291 if last_segment in vuid_mapping.implicit_type_map:
292 implicit = True
293 elif not last_segment.isdigit(): # Explicit ids should only have digits in last segment
294 print ("ERROR: Found last segment of val error ID that isn't in implicit map and doesn't numbers in last segment: %s" % (last_segment))
295 sys.exit()
296 self.error_db_dict[error_enum]['implicit'] = implicit
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600297if __name__ == "__main__":
298 i = 1
299 use_online = True # Attempt to grab spec from online by default
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600300 while (i < len(sys.argv)):
301 arg = sys.argv[i]
302 i = i + 1
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600303 if (arg == '-json-file'):
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600304 json_filename = sys.argv[i]
305 i = i + 1
Tobin Ehlis828781a2017-05-23 15:23:40 -0600306 elif (arg == '-json'):
307 read_json = True
Tobin Ehlis2c932132017-05-19 16:32:15 -0600308 elif (arg == '-json-compare'):
309 json_compare = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600310 elif (arg == '-out'):
311 out_filename = sys.argv[i]
312 i = i + 1
313 elif (arg == '-gendb'):
314 gen_db = True
315 # Set filename if supplied, else use default
316 if i < len(sys.argv) and not sys.argv[i].startswith('-'):
317 db_filename = sys.argv[i]
318 i = i + 1
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600319 elif (arg == '-update'):
Tobin Ehlis3c37fb32017-05-24 09:31:13 -0600320 read_json = True
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600321 json_compare = True
322 gen_db = True
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600323 elif (arg in ['-help', '-h']):
324 printHelp()
325 sys.exit()
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600326 spec = Specification()
Tobin Ehlis828781a2017-05-23 15:23:40 -0600327 if read_json:
328 spec.readJSON()
Tobin Ehlis98d109a2017-05-11 14:42:38 -0600329 spec.parseJSON()
Tobin Ehlis2c932132017-05-19 16:32:15 -0600330 #sys.exit()
331 if (json_compare):
332 # Read in current spec info from db file
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600333 (orig_err_msg_dict) = spec.readDB(db_filename)
Tobin Ehlis2c932132017-05-19 16:32:15 -0600334 spec.compareJSON()
335 print ("Found %d missing db entries in json db" % (spec.json_missing))
336 print ("Found %d duplicate json entries" % (spec.duplicate_json_key_count))
Tobin Ehlisda3916c2017-05-24 14:13:46 -0600337 spec.genDB(db_filename)
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600338 if (gen_db):
339 spec.genDB(db_filename)
Tobin Ehlis3198ba32017-04-19 17:30:52 -0600340 print ("Writing out file (-out) to '%s'" % (out_filename))
Tobin Ehlis5ade0692016-10-05 17:18:15 -0600341 spec.genHeader(out_filename)