Harald Welte | cef7ef6 | 2017-01-22 19:04:08 +0100 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Code to parse the ASCII Database files of QXDM |
| 4 | # (C) 2017 by Harald Welte <laforge@gnumonks.org> |
| 5 | # |
| 6 | # This program is free software; you can redistribute it and/or modify |
| 7 | # it under the terms of the GNU General Public License as published by |
| 8 | # the Free Software Foundation; either version 2 of the License, or |
| 9 | # (at your option) any later version. |
| 10 | # |
| 11 | # This program is distributed in the hope that it will be useful, |
| 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | # GNU General Public License for more details. |
| 15 | # |
| 16 | # You should have received a copy of the GNU General Public License along |
| 17 | # with this program; if not, write to the Free Software Foundation, Inc., |
| 18 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 19 | |
| 20 | import csv |
| 21 | |
| 22 | def export_value_str(name, vals, flavor='osmocom'): |
| 23 | if flavor == 'osmocom': |
| 24 | print("const struct value_string %s[] = {" % name); |
| 25 | elif flavor == 'wireshark': |
| 26 | print("const value_string %s[] = {" % name); |
| 27 | for v in sorted(vals.iterkeys(), key=int): |
| 28 | print("\t{ %d, \"%s\" }," % (int(v), vals[v])); |
| 29 | print("\t{ 0, NULL }") |
| 30 | print("};"); |
| 31 | |
| 32 | class QxdmDb(object): |
| 33 | file_fields = { |
| 34 | 'Enum': ['id', 'name', 'entries_id', 'unknown'], |
| 35 | 'EnumEntry': ['enum_id', 'value', 'name', 'unknown'], |
| 36 | 'EventID': ['value', 'name', 'category_id', 'description_id'], |
| 37 | 'EventCategory': ['value', 'name', 'unknown', 'unknown2'], |
| 38 | 'Struct': ['id', 'index', 'unknown', 'field_id', 'unknown2', 'unknown3', 'unknown4'], |
| 39 | 'Field': ['id', 'name', 'bits', 'unknown1', 'unknown2', |
| 40 | 'unknown3', 'unknown4', 'unknown5'], |
| 41 | 'Description': ['id', 'text'], |
| 42 | 'LogItem': ['id', 'name', 'category_id', 'unknown'], |
| 43 | 'LogCategory': ['id', 'name', 'unknown', 'parent_id'], |
| 44 | 'MessageLevel': ['id', 'level', 'name', 'category_id'], |
| 45 | 'MessageCategory': ['id', 'name', 'unknown', 'parent_id'], |
| 46 | } |
| 47 | _csvdicts= {} |
| 48 | |
| 49 | descs = {} |
| 50 | enums = {} |
| 51 | events = {} |
| 52 | event_cats = {} |
| 53 | logitems = {} |
| 54 | log_cats = {} |
| 55 | msgs = {} |
| 56 | msg_cats = {} |
| 57 | |
| 58 | @staticmethod |
| 59 | def read_into_dict(fname, fieldnames=None): |
| 60 | csvfile = open(fname, 'rb') |
| 61 | r = csv.DictReader(csvfile, fieldnames=fieldnames, delimiter='^') |
| 62 | return r |
| 63 | |
| 64 | def gen_descs(self): |
| 65 | for d in self._csvdicts['Description']: |
| 66 | self.descs[int(d['id'], base=0)] = d['text'] |
| 67 | |
| 68 | def gen_enums(self): |
| 69 | for e in self._csvdicts['Enum']: |
| 70 | self.enums[int(e['id'], base=0)] = {'name': e['name'], 'entries': {}} |
| 71 | for ee in self._csvdicts['EnumEntry']: |
| 72 | self.enums[int(ee['enum_id'], base=0)]['entries'][int(ee['value'],base=0)] = ee['name'] |
| 73 | |
| 74 | def gen_events(self): |
| 75 | for c in self._csvdicts['EventCategory']: |
| 76 | self.event_cats[int(c['value'],base=0)] = {'name': c['name'], 'events': []} |
| 77 | |
| 78 | for e in self._csvdicts['EventID']: |
| 79 | val_int = int(e['value'], base=0) |
| 80 | self.events[val_int] = {'name': e['name']} |
| 81 | if e['description_id'] != '-1': |
| 82 | self.events[val_int]['description'] = self.descs[int(e['description_id'], base=0)] |
| 83 | cats = e['category_id'].split(',') |
| 84 | for c in cats: |
| 85 | cat_int = int(c, base=0) |
| 86 | if cat_int in self.event_cats: |
| 87 | self.event_cats[cat_int]['events'].append(self.events[val_int]) |
| 88 | |
| 89 | def gen_logitems(self): |
| 90 | for c in self._csvdicts['LogCategory']: |
| 91 | self.log_cats[int(c['id'],base=0)] = {'name': c['name'], 'items': []} |
| 92 | |
| 93 | for l in self._csvdicts['LogItem']: |
| 94 | val_int = int(l['id'], base=0) |
| 95 | self.logitems[val_int] = {'name': l['name']} |
| 96 | |
| 97 | cats = l['category_id'].split(',') |
| 98 | for c in cats: |
| 99 | cat_int = int(c, base=0) |
| 100 | if cat_int in self.log_cats: |
| 101 | self.log_cats[cat_int]['items'].append(self.logitems[val_int]) |
| 102 | |
| 103 | def gen_msglevels(self): |
| 104 | def strip_suffix(s): |
| 105 | slash = s.rfind('/') |
| 106 | if slash == -1: |
| 107 | return s |
| 108 | else: |
| 109 | return s[:slash] |
| 110 | for c in self._csvdicts['MessageCategory']: |
| 111 | self.msg_cats[int(c['id'],base=0)] = {'name': c['name'], 'msgs': []} |
| 112 | |
| 113 | for l in self._csvdicts['MessageLevel']: |
| 114 | val_int = int(l['id'], base=0) |
| 115 | level_int = int(l['level'], base=0) |
| 116 | if not val_int in self.msgs: |
| 117 | self.msgs[val_int] = {'levels':{}, 'name': strip_suffix(l['name'])} |
| 118 | self.msgs[val_int]['levels'][level_int] = {'name': l['name']} |
| 119 | |
| 120 | cats = l['category_id'].split(',') |
| 121 | for c in cats: |
| 122 | cat_int = int(c, base=0) |
| 123 | if cat_int in self.msg_cats: |
| 124 | self.msg_cats[cat_int]['msgs'].append(self.msgs[val_int]['levels'][level_int]) |
| 125 | |
| 126 | |
| 127 | def __init__(self, dir_to_db): |
| 128 | for f in self.file_fields: |
| 129 | fname = '%s/%s.txt' % (dir_to_db, f) |
| 130 | self._csvdicts[f] = self.read_into_dict(fname, self.file_fields[f]) |
| 131 | self.gen_descs() |
| 132 | self.gen_enums() |
| 133 | self.gen_events() |
| 134 | self.gen_logitems() |
| 135 | self.gen_msglevels() |
| 136 | |
| 137 | def export_valstr_events(self): |
| 138 | def f(v): |
| 139 | return v['name'] |
| 140 | vals = dict(zip(self.events, map(f, self.events.values()))) |
| 141 | export_value_str('diag_event_vals', vals) |
| 142 | |
| 143 | def export_valstr_event_descs(self): |
| 144 | vals = {} |
| 145 | for e in self.events: |
| 146 | if 'description' in self.events[e]: |
| 147 | vals[e] = self.events[e]['description'] |
| 148 | export_value_str('diag_event_descs', vals) |
| 149 | |
| 150 | def export_valstr_logitems(self): |
| 151 | def f(v): |
| 152 | return v['name'] |
| 153 | vals = dict(zip(self.logitems, map(f, self.logitems.values()))) |
| 154 | export_value_str('diag_log_item_vals', vals) |
| 155 | |
| 156 | def export_valstr_msgs(self): |
| 157 | def f(v): |
| 158 | return v['name'] |
| 159 | vals = dict(zip(self.msgs, map(f, self.msgs.values()))) |
| 160 | export_value_str('diag_msg_vals', vals) |