blob: d8791b4c5f9b87a55a99012be05eccb35ab437cb [file] [log] [blame]
rjw6c1fd8f2022-11-30 14:33:01 +08001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3import re
4import os
5import json
6import chardet
7import logging
8import argparse
9from tempfile import mkstemp
10from shutil import move, copy
11class ParserState():
12 EXPECT_BEGIN='(BEGIN_TRACE_MAP_WITH_RANGE|BEGIN_TRACE_MAP)\(\s*(\w+)\s*(,*\s*(\d+)\s*)?\s*(,*\s*(\d+)\s*)?\)'
13 TRC_MSG= r'TRC_MSG\s*\(\s*([_a-zA-Z][_a-zA-Z0-9]+)\s*,\s*\"((\\.|[^"\\])*)\"(\w+\"(\\.|[^"\\]*)\")*\s*\)'
14 END_TRACE_MAP='(END_TRACE_MAP_WITH_RANGE|END_TRACE_MAP)\(\s*(\w+)\s*(,*\s*(\d+)\s*)?\s*(,*\s*(\d+)\s*)?\)'
15args = None
16module = 'DUMMY'
17legacyParams = {}
18msgs = []
19moduleList = []
20classes = [
21 { 'TRACE_INFO': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
22 { 'TRACE_WARNING': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
23 { 'TRACE_ERROR': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
24 { 'TRACE_FUNC': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
25 { 'TRACE_STATE': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
26 { 'TRACE_GROUP1': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
27 { 'TRACE_GROUP2': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
28 { 'TRACE_GROUP3': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
29 { 'TRACE_GROUP4': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
30 { 'TRACE_GROUP5': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
31 { 'TRACE_GROUP6': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
32 { 'TRACE_GROUP7': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
33 { 'TRACE_GROUP8': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
34 { 'TRACE_GROUP9': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } },
35 { 'TRACE_GROUP10': { 'tag': ['Baseline'], 'traceType': 'Public', 'debugLevel': 'Ultra-Low' } }
36]
37
38def init_logger(log_filename):
39 logging.basicConfig(level=logging.DEBUG,
40 format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
41 datefmt='%m-%d %H:%M:%S',
42 filename=log_filename)
43 console = logging.StreamHandler()
44 console.setLevel(logging.DEBUG)
45 formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
46 console.setFormatter(formatter)
47 logging.getLogger('').addHandler(console)
48def parsePsTrcPreprocessed(pstrc_file, inc_path):
49 global moduleList
50 tmp_h, tmp_pstrc_file = mkstemp()
51 with os.fdopen(tmp_h, 'w') as new_file:
52 prep_pstrc_file = pstrc_file+'.tmp'
53 logging.info('PreProcessing {}'.format(prep_pstrc_file))
54 os.system(r'gcc -fdirectives-only -P -E -I{} -Iinterface/service/kal/ -Iinterface/service/config/ -Iinterface/sap -I interface/service/dhl/v2 -I interface/service/dhl -I interface/service/config/kal_config/ -I interface/driver/regbase -I interface/service/event_info -D __VGTCM__ -D __LPP_CP_SUPPORT__ -D __MD97__ -D MT6297 -D __TST_MODULE__ -D GEN_FOR_PC {} | gcc -fpreprocessed -dD -E -P - > {}'.format(inc_path, pstrc_file, prep_pstrc_file))
55 parsePsTrc(prep_pstrc_file, new_file)
56 logging.info('Processing {}'.format(pstrc_file))
57 parserState = ParserState.EXPECT_BEGIN
58 tmp_h, tmp_pstrc_file = mkstemp()
59 with os.fdopen(tmp_h, 'w') as new_file:
60 file = open(pstrc_file)
61 line = file.readline()
62 while line:
63 stripped= line.rstrip().lstrip()
64 if stripped == '':
65 line = file.readline()
66 continue
67 logging.debug('[IO] State {}: line: {}'.format(parserState, stripped))
68 if parserState == ParserState.EXPECT_BEGIN:
69 if re.match(ParserState.EXPECT_BEGIN, stripped, re.IGNORECASE):
70 match = re.search(ParserState.EXPECT_BEGIN, stripped)
71 if match:
72 parserState = ParserState.TRC_MSG
73 else:
74 new_file.write(line)
75 else:
76 new_file.write(line)
77 elif parserState == ParserState.TRC_MSG:
78 if re.match(ParserState.END_TRACE_MAP, stripped, re.IGNORECASE):
79 _m = moduleList.pop(0)
80 j = json.dumps(_m,
81 sort_keys=True,
82 # escape utf-8 to ascii
83 ensure_ascii=True,
84 indent=2
85 )
86 filename = os.path.splitext(pstrc_file)[0] +'_'+ _m['module'].lower() + '_utmd.json'
87 new_file.write('// The trace map of {} is converted to UTMD file.\n'.format(module))
88 new_file.write('// If you wished to modify your trace, please refer to {}\n'.format(os.path.basename(filename)))
89 new_file.write('#include"{}_precodegen.h"\n'.format(os.path.splitext(os.path.basename(filename))[0]))
90 parserState = ParserState.EXPECT_BEGIN
91 else:
92 new_file.write(line)
93 line = file.readline()
94 #force output for lpp_trc.h (no END_TRACE_MAP in file...)
95 for _m in moduleList:
96 filename = os.path.splitext(pstrc_file)[0] +'_'+ _m['module'].lower() + '_utmd.json'
97 new_file.write('// The trace map of {} is converted to UTMD file.\n'.format(module))
98 new_file.write('// If you wished to modify your trace, please refer to {}\n'.format(os.path.basename(filename)))
99 new_file.write('#include"{}_precodegen.h"\n'.format(os.path.splitext(os.path.basename(filename))[0]))
100 if pstrc_file.endswith('lpp_trc.h'):
101 new_file.write('#endif /* _LPP_TRC_H */\n')
102 move(tmp_pstrc_file, pstrc_file)
103def parsePsTrc(pstrc_file, new_file):
104 global module
105 global legacyParams
106 global classes
107 global msgs
108 global moduleList
109 logging.info('Processing {}'.format(pstrc_file))
110 os.system(r"sed -i -E ':a;N;$!ba;s/(TRC_MSG)\s*\(\s*(\w+)\s*,\n/\1\(\2, /g;:a:N;$!ba;s/\\\n//g' {}".format(pstrc_file))
111 parserState = ParserState.EXPECT_BEGIN
112 with open(pstrc_file) as file:
113 line = file.readline()
114 while line:
115 stripped= line.rstrip().lstrip()
116 if stripped == '':
117 line = file.readline()
118 continue
119 logging.debug('[IO] State {}: line: {}'.format(parserState, stripped))
120 if parserState == ParserState.EXPECT_BEGIN:
121 if re.match(ParserState.EXPECT_BEGIN, stripped, re.IGNORECASE):
122 match = re.search(ParserState.EXPECT_BEGIN, stripped)
123 if match:
124 global module
125 module = match.group(2)
126 if match.group(4) and match.group(6):
127 legacyParams.update( {'predefinedMessageRange': { 'min': int(match.group(4)), 'max': int(match.group(6)) } } )
128 else:
129 logging.warning("4th group / 6th group not found")
130 parserState = ParserState.TRC_MSG
131 else:
132 new_file.write(line)
133 else:
134 new_file.write(line)
135 elif parserState == ParserState.TRC_MSG:
136 if stripped.startswith('/*'):
137 while not stripped.endswith('*/'):
138 c = file.read(1)
139 stripped = stripped + c
140 line = file.readline()
141 continue
142 if stripped.startswith('TRC_MSG'):
143 while not re.match(ParserState.TRC_MSG, stripped, re.IGNORECASE) and line:
144 if stripped.endswith('\\'):
145 stripped = stripped[:-1:]
146 line = file.readline().lstrip().rstrip()
147 stripped = stripped + line
148 logging.error('strip anti-slash {}'.format(stripped))
149 else:
150 line = file.readline().lstrip().rstrip()
151 stripped = stripped + line
152 logging.error('strip anti-slash {}'.format(stripped))
153 # detect character encoding and transform to utf8
154 if chardet.detect(stripped)['confidence'] > 0.75:
155 logging.debug('decode by {}'.format(chardet.detect(stripped)['encoding']))
156 stripped = stripped.decode(chardet.detect(stripped)['encoding']).encode('utf8')
157 match = re.search(ParserState.TRC_MSG, stripped)
158 trc = {}
159 trc['traceClass'] = 'TRACE_INFO'
160 if match.group(4):
161 trc['format'] = match.group(2) + re.sub('"', '', match.group(4))
162 else:
163 trc['format'] = match.group(2)
164 if not filter( lambda x: match.group(1) in x, msgs):
165 msgs.append( { match.group(1): trc } )
166 else:
167 logging.error('Msg redefined {}'.format(match.group(1)))
168 logging.debug(match)
169 elif re.match(ParserState.END_TRACE_MAP, stripped, re.IGNORECASE):
170 moduleList.append({'module':module,
171 'legacyParameters': legacyParams,
172 'traceClassDefs': classes,
173 'traceDefs': msgs,
174 'traceFamily': 'PS'
175 })
176 j = json.dumps({'module':module,
177 'legacyParameters': legacyParams,
178 'traceClassDefs': classes,
179 'traceDefs': msgs,
180 'traceFamily': 'PS'
181 },
182 sort_keys=True,
183 # escape utf-8 to ascii
184 ensure_ascii=True,
185 indent=2
186 )
187 filename = os.path.splitext(os.path.splitext(pstrc_file)[0])[0] +'_'+ module.lower() + '_utmd.json'
188 logging.warning('write to {}'.format(filename))
189 utmd_file = open(filename, 'w')
190 utmd_file.write(j)
191 new_file.write('// The trace map of {} is converted to UTMD file.\n'.format(module))
192 new_file.write('// If you wished to modify your trace, please refer to {}\n'.format(os.path.basename(filename)))
193 new_file.write('#include"{}_precodegen.h"\n'.format(os.path.splitext(os.path.basename(filename))[0]))
194 parserState = ParserState.EXPECT_BEGIN
195 module = 'DUMMY'
196 legacyParams = {}
197 msgs = []
198 else:
199 new_file.write(line)
200 line = file.readline()
201def main():
202 global args
203 parser = argparse.ArgumentParser(description='PSTRC-UTMD: UTMD file will be automatically generated aside pstrc_file\n\
204 xxx_trc.h -> xxx_trc_utmd.json for single trace_map header\n\
205 xxx_trc.h -> xxx_trc_mod_ooo_utmd.json, xxx_trc_mod_abc_utmd.json for multiple trace_map header\n\
206 in this case the there are trace_map for MOD_OOO and MOD_ABC',
207 #formatter_class=argparse.ArgumentDefaultsHelpFormatter)
208 formatter_class=argparse.RawDescriptionHelpFormatter)
209 parser.add_argument("-v", action="version", version='1.0.0')
210 parser.add_argument("pstrc_file",
211 help="input PS TRC file")
212 parser.add_argument("-l", dest="log_file",
213 help="log file",
214 default='legacy-ps-utmd.log',
215 action="store")
216 args = parser.parse_args()
217 if args.pstrc_file is None:
218 parser.print_help()
219 quit()
220 init_logger(args.log_file)
221 copy(args.pstrc_file, args.pstrc_file+'.bak')
222 expand_file_mapping = {'lpp_trc': 'protocol/agps/lpp/include/',
223 'mod_dast_trc': 'protocol/ddm/mod_dast/include/',
224 'vgsm_trc': 'protocol/interface/vgnas/trace/',
225 'ltecsr_trc': 'protocol/lte_csr/csr/inc/',
226 'SST_trc': 'service/sst/include/',
227 'tcm_trc': 'protocol/layer4/l4/tcm/common/'
228 }
229 if(args.pstrc_file.endswith('lpp_trc.h') or
230 args.pstrc_file.endswith('mod_dast_trc.h') or
231 args.pstrc_file.endswith('vgsm_trc.h') or
232 args.pstrc_file.endswith('ltecsr_trc.h') or
233 args.pstrc_file.endswith('SST_trc.h') or
234 os.path.basename(args.pstrc_file) == 'tcm_trc.h'
235 ):
236 logging.info('Inc path: {}'.format(expand_file_mapping[ os.path.splitext(os.path.basename(args.pstrc_file))[0] ]) )
237 parsePsTrcPreprocessed(args.pstrc_file, expand_file_mapping[ os.path.splitext(os.path.basename(args.pstrc_file))[0] ])
238 else:
239 tmp_h, tmp_pstrc_file = mkstemp()
240 with os.fdopen(tmp_h, 'w') as new_file:
241 parsePsTrc(args.pstrc_file, new_file)
242 move(tmp_pstrc_file, args.pstrc_file)
243if __name__ == '__main__':
244 main()
245