blob: e555e592f87d300c76b00994823d35eee410caf6 [file] [log] [blame]
Jianliang Shen9b4ba112022-01-19 14:57:04 +08001# ------------------------------------------------------------------------------
2# Copyright (c) 2022, Arm Limited. All rights reserved.
3#
4# SPDX-License-Identifier: BSD-3-Clause
5#
6# ------------------------------------------------------------------------------
7
8import sqlite3
9import curses
10import curses.textpad
11
12class UI(object):
13 """
14 Class UI is used to show the data in the terminal with library curses. It
15 contains two main diffrent functions, one is to control the UI and show the
16 message in the terminal, the other is to search the information and then
17 transform it into a string varible called items[]. This can be showed or
18 exported as a plaintext. These functions to fill items[] are PUBLIC.
19
20 - Methods:
21 - UI().run() - Run the UI in terminal.
22 - UI.draw_<symbol>_page() - Get the information of specific symbol
23
24 - Variables:
25 - UI().items - The result searched from database.
26 - UI().armcc - ARMCLANG option.
27 - UI().gnuarm - GNUARM option.
28 - UI().con - Database handler.
29 - UI().function_name - Specific function name.
30 - UI().data_name - Specific data name.
31 - UI().section_name - Specific section name.
32 - UI().library_name - Specific library name.
33 - UI().obj_file - Specific object file name.
34 """
35
36 def __init__(self):
37 """
38 Initialize variables.
39 """
40 self.function_name = ""
41 self.data_name = ""
42 self.section_name = ""
43 self.library_name = ""
44 self.obj_file = ""
45 self.gnuarm = False
46 self.armcc = False
47 self.items = []
48 self.con = sqlite3.connect("data.db")
49
50 self.__cur = self.con.cursor()
51 self.__window = None
52 self.__width = 0
53 self.__height = 0
54 self.__menu_depth = 0
55 self.__detail = 0
56 self.__section_detail = 0
57 self.__UP = -1
58 self.__DOWN = 1
59 self.__line1 = "─" * 128
60 self.__line2 = "-" * 128
61 self.__cmd_file="Enter the file name:"
62 self.__cmd_func="Enter the function name:"
63 self.__cmd_data="Enter the data name:"
64
65 def __init_curses(self):
66 """
67 Setup the curses
68 """
69 self.__window = curses.initscr()
70 self.__window.keypad(True)
71
72 curses.noecho()
73 curses.cbreak()
74 curses.curs_set(False)
75
76 curses.start_color()
77 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
78 curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_WHITE)
79
80 self.__current = curses.color_pair(2)
81 self.__height, self.__width = self.__window.getmaxyx()
82
83 self.__max_lines = curses.LINES - 1
84 self.__top = 0
85
86 self.__bottom = len(self.items)
87 self.__current = 0
88 self.__current_x = 0
89
90 def __input_stream(self):
91 """
92 Waiting an input and run a proper method according to type of input
93 """
94 while True:
95 self.__display()
96
97 ch = self.__window.getch()
98 if ch == curses.KEY_UP:
99 self.__scroll(self.__UP)
100 elif ch == curses.KEY_DOWN:
101 self.__scroll(self.__DOWN)
102 elif ch == curses.KEY_LEFT:
103 self.__current_x = max(self.__current_x - 1, 0)
104 elif ch == curses.KEY_RIGHT:
105 self.__current_x = self.__current_x + 1
106 elif ch == ord('q') or ch == ord('Q'):
107 """
108 If press 'q' or 'Q', escape this page
109 """
110 if self.__menu_depth == 0:
111 break
112 self.__menu_depth = max(self.__menu_depth - 1, 0)
113 self.__draw_page()
114 elif ch == 10:
115 """
116 If press ENTER, get into next page if it exists
117 """
118 self.__get_menu_choose()
119 self.__menu_depth = self.__menu_depth + 1
120 self.__draw_page()
121 elif ch == 58:
122 """
123 If press ':', get target name form input line to search
124 functions or data
125 """
126 if self.__menu_depth == 1:
127 if self.__detail == 3:
128 self.draw_function_page(self.__get_input_line_msg(self.__cmd_func))
129 if self.__detail == 4:
130 self.draw_data_page(self.__get_input_line_msg(self.__cmd_data))
131 elif ch == ord('s') or ch == ord('S'):
132 """
133 If press 's' or 'S', save to file
134 """
135 self.__save_file(self.__get_input_line_msg(self.__cmd_file))
136
137 def __get_input_line_msg(self, cmd):
138 """
139 Get message from input line.
140 """
141 self.__window.addstr(self.__height - 1, 0, cmd, curses.color_pair(2))
142 self.input_line = curses.newwin(1, curses.COLS - 2 - len(cmd), curses.LINES-1, len(cmd) + 1)
143 self.input_box = curses.textpad.Textbox(self.input_line)
144 self.__window.refresh()
145 self.input_box.edit()
146 ret = self.input_box.gather()[:len(self.input_box.gather())-1]
147 self.__display()
148 self.input_line.clear()
149 return ret
150
151 def __save_file(self, output_file_name):
152 """
153 Save to files
154 """
155 fo = open(output_file_name + '.txt', "w")
156 for s in self.items:
157 fo.write(s + '\n')
158 fo.close()
159
160 def __scroll(self, direction):
161 """
162 Scrolling the window when pressing up/down arrow keys
163 """
164 next_line = self.__current + direction
165 if (direction == self.__UP) and (self.__top > 0 and self.__current == 0):
166 self.__top += direction
167 return
168 if (direction == self.__DOWN) and (next_line == self.__max_lines) and \
169 (self.__top + self.__max_lines < self.__bottom):
170 self.__top += direction
171 return
172 if (direction == self.__UP) and (self.__top > 0 or self.__current > 0):
173 self.__current = next_line
174 return
175 if (direction == self.__DOWN) and (next_line < self.__max_lines) and \
176 (self.__top + next_line < self.__bottom):
177 self.__current = next_line
178 return
179
180 def __display(self):
181 """
182 Display the items on window
183 """
184 self.__window.erase()
185 for idx, item in enumerate(self.items[self.__top:self.__top + self.__max_lines]):
186 if idx == self.__current:
187 self.__window.addstr(idx, 0, item[self.__current_x:self.__current_x + self.__width], curses.color_pair(2))
188 else:
189 self.__window.addstr(idx, 0, item[self.__current_x:self.__current_x + self.__width], curses.color_pair(1))
190 self.__window.refresh()
191
192 def __draw_page(self):
193 """
194 Draw different page with menu_depth, detail and section_detail.
195 """
196 if self.__menu_depth == 0:
197 self.__draw_welcome_page()
198 elif self.__menu_depth == 1:
199 if self.__detail == 1:
200 self.draw_summary_page()
201 if self.__detail == 2:
202 self.draw_section_page()
203 if self.__detail == 3:
204 self.draw_function_page("")
205 if self.__detail == 4:
206 self.draw_data_page("")
207 if self.__detail == 5:
208 self.draw_library_page()
209 if self.__detail == 6:
210 self.draw_obj_page()
211 elif self.__menu_depth == 2:
212 if self.__detail == 2:
213 self.draw_section_detail_page()
214 if self.__detail == 3:
215 self.draw_function_detail_page()
216 if self.__detail == 4:
217 self.draw_data_detail_page()
218 if self.__detail == 5:
219 self.draw_library_detail_page()
220 if self.__detail == 6:
221 self.draw_obj_detail_page()
222 elif self.__menu_depth == 3 and self.__detail == 2:
223 """
224 Draw section detail menu, here self.__detail is 2
225 """
226 if self.__section_detail == 1:
227 self.draw_section_lib()
228 if self.__section_detail == 2:
229 self.draw_section_func()
230 if self.__section_detail == 3:
231 self.draw_section_data()
232 elif self.__menu_depth == 4:
233 """
234 Only section detail menu can move to menu depth 5, here function
235 detail and data detail are also supported.
236 """
237 if self.__section_detail == 2:
238 self.draw_function_detail_page()
239 if self.__section_detail == 3:
240 self.draw_data_detail_page()
241
242 self.__bottom = len(self.items)
243 self.__current = 0
244 self.__current_x = 0
245 self.__top = 0
246
247 def __get_menu_choose(self):
248 """
249 Get options from menus or specific objects like function, data, library
250 or object files.
251 """
252
253 """
254 First page, menu_depth = 1
255 =============================
256 Current file: tfm_s.axf
257 1. Summary Info -->
258 2. Section Module -->
259 3. Function detail -->
260 4. Data detail -->
261 5. Library Summary -->
262 6. Object files Summary -->
263 =============================
264 It will change the self.__detail's value in range 1 - 6
265 """
266 if self.__menu_depth == 0:
267 if self.__current + self.__top > 0:
268 self.__detail = self.__current
269 else:
270 """
271 Except first line
272 """
273 self.__menu_depth = self.__menu_depth - 1
274 if self.__menu_depth == 1:
275 if self.__current + self.__top > 0:
276 if self.__detail == 2:
277 """
278 Get section name which will be used to draw its detail page
279 in __draw_page() function.
280 """
281 self.section_name = self.items[self.__top + self.__current].split()[0]
282 elif self.__detail == 3:
283 """
284 Get function name and its object file to avoid same name
285 situation. Function name will be used to draw its detail
286 page in __draw_page() function.
287 """
288 self.function_name = self.items[self.__top + self.__current].split()[0]
289 self.obj_file = self.items[self.__top + self.__current].split()[4]
290 elif self.__detail == 4:
291 """
292 Get data name and its object file name to avoid same name
293 situation. Data name will be used to draw its detail page in
294 __draw_page() function.
295 """
296 self.data_name = self.items[self.__top + self.__current].split()[0]
297 self.obj_file = self.items[self.__top + self.__current].split()[5]
298 elif self.__detail == 5:
299 """
300 Get library name which will be used to draw its detail page
301 in __draw_page() function.
302 """
303 self.library_name = self.items[self.__top + self.__current].split()[0]
304 elif self.__detail == 6:
305 """
306 Get object file name which will be used to draw its detail
307 page in __draw_page() function.
308 """
309 self.obj_file = self.items[self.__top + self.__current].split()[0]
310 else:
311 """
312 Other invalid choose will not change menu depth.
313 """
314 self.__menu_depth = self.__menu_depth - 1
315 else:
316 """
317 Except first line
318 """
319 self.__menu_depth = self.__menu_depth - 1
320 """
321 Section detail page, menu_depth = 1
322 =============================
323 Name :TFM_UNPRIV_CODE Size :155544
324 1. Summary -->
325 2. Function -->
326 3. Data -->
327 =============================
328 It will change the self.__section_detail's value in range 1 - 3
329 """
330 if self.__menu_depth == 2:
331 if self.__current + self.__top > 0:
332 if self.__detail == 2:
333 self.__section_detail = self.__current
334 else:
335 self.__menu_depth = self.__menu_depth - 1
336 else:
337 self.__menu_depth = self.__menu_depth - 1
338 if self.__menu_depth == 3:
339 if self.__current + self.__top > 0:
340 if self.__section_detail == 2:
341 self.function_name = self.items[self.__top + self.__current].split()[0]
342 self.obj_file = self.items[self.__top + self.__current].split()[4]
343 elif self.__section_detail == 3:
344 self.data_name = self.items[self.__top + self.__current].split()[0]
345 self.obj_file = self.items[self.__top + self.__current].split()[5]
346 else:
347 self.__menu_depth = self.__menu_depth - 1
348 else:
349 self.__menu_depth = self.__menu_depth - 1
350 if self.__menu_depth == 4:
351 self.__menu_depth = self.__menu_depth - 1
352
353 def __draw_welcome_page(self):
354 self.items = ["Code Size Analysis Tool for Map File",
355 "1. Summary Info -->",
356 "2. Section Module -->",
357 "3. Function detail -->",
358 "4. Data detail -->",
359 "5. Library Summary -->",
360 "6. Object files Summary -->"]
361
362 def draw_summary_page(self):
363 """
364 Get summary info from database and save into self.items.
365 """
366 cursor = self.__cur.execute("select * from Summary")
367 if self.gnuarm:
368 for row in cursor:
369 self.items = [self.__line1,
370 "Total usage(include all symbols and \"fill or pad\"):",
371 "Flash size\t: {:<8}\t{:<4.2f}\tKB".
372 format(row[6], row[6]/1024),
373 "RAM size\t: {:<8}\t{:<4.2f}\tKB".
374 format(row[7], row[7]/1024),
375 self.__line2,
376 "These data are collected from functions, stacks or arrays sizes without \"fill or pad\" part!",
377 "Text size\t: {:<8}\t{:<4.2f}\tKB".
378 format(row[0], row[0]/1024),
379 "Read-only data\t: {:<8}\t{:<4.2f}\tKB".
380 format(row[1], row[1]/1024),
381 "Read-write data\t: {:<8}\t{:<4.2f}\tKB".
382 format(row[2], row[2]/1024),
383 "BSS data\t: {:<8}\t{:<4.2f}\tKB".
384 format(row[3], row[3]/1024),
385 self.__line2,
386 "Some other unknown type symbols locate in flash or ram:",
387 "Total unknown type symbols in flash: {:<8}\t{:<4.2f}\tKB".
388 format(row[4], row[4]/1024),
389 "Total unknown type symbols in RAM : {:<8}\t{:<4.2f}\tKB".
390 format(row[5], row[5]/1024),
391 self.__line1]
392 break
393 if self.armcc:
394 for row in cursor:
395 self.items = ["Code size\t: {:<8}\t{:<4.2f}\tKB".
396 format(row[0], row[0]/1024),
397 "RO data\t\t: {:<8}\t{:<4.2f}\tKB".
398 format(row[1], row[1]/1024),
399 "RW data\t\t: {:<8}\t{:<4.2f}\tKB".
400 format(row[2], row[2]/1024),
401 "ZI data\t\t: {:<8}\t{:<4.2f}\tKB".
402 format(row[3], row[3]/1024),
403 "Flash size\t: {:<8}\t{:<4.2f}\tKB = Code + RO + RW".
404 format(row[6], row[6]/1024),
405 "RAM size\t: {:<8}\t{:<4.2f}\tKB = RW + ZI".
406 format(row[7], row[7]/1024)]
407 break
408
409 def draw_section_page(self):
410 """
411 Get section info from database and save into self.items.
412 """
413 self.items = ["{:<50}{:<16}{:<16}{:<16}".
414 format("Name", "Size", "Address", "PAD size")]
415
416 cursor = self.__cur.execute("select * from Section ORDER BY size DESC")
417 for row in cursor:
418 self.items.append("{:<50}{:<16}{:<16}{:<16}".
419 format(row[0], row[1], row[2], row[3]))
420
421 def draw_section_detail_page(self):
422 """
423 Section detail page with a menu.
424 """
425 cursor = self.__cur.execute("select * from Section WHERE name = '{}'".
426 format(self.section_name))
427 for row in cursor:
428 self.items = ["Name :{}\t\tSize :{}".
429 format(self.section_name, row[1]),
430 "1. Summary -->",
431 "2. Function -->",
432 "3. Data -->"]
433 break
434
435 def draw_section_lib(self):
436 lib_dict, obj_dict = {}, {}
437 lib_list, obj_list = [], []
438 exsit_no_lib_obj = False
439 tmp_list = []
440 colums_name = "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".format(
441 "Name", "Flash", "RAM", "Code", "RO data", "RW data", "ZI data", "Total")
442 count = 0
443
444 """
445 Get detail information with functions and data from tables in database
446 with a dictionary in python.
447 """
448 cursor = self.__cur.execute("select * from Function WHERE section = '{}' ORDER BY lib_file DESC".
449 format(self.section_name))
450 for row in cursor:
451 lib_name = row[5]
452 if lib_name in lib_dict.keys():
453 lib_dict[lib_name]['Code'] += row[2]
454 else:
455 lib_dict[lib_name] = {'RO': 0, 'RW': 0,
456 'Code': row[2], 'ZI': 0}
457
458 obj_name = row[4]
459 if obj_name in obj_dict.keys():
460 obj_dict[obj_name]['Code'] += row[2]
461 else:
462 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
463 'Code': row[2], 'Lib': lib_name, 'ZI': 0}
464
465 cursor = self.__cur.execute("select * from Data WHERE section = '{}' ORDER BY lib_file DESC".
466 format(self.section_name))
467 for row in cursor:
468 lib_name = row[6]
469 if lib_name in lib_dict.keys():
470 lib_dict[lib_name][row[4]] += row[2]
471 else:
472 lib_dict[lib_name] = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0}
473 lib_dict[lib_name][row[4]] = row[2]
474
475 obj_name = row[5]
476 if obj_name in obj_dict.keys():
477 obj_dict[obj_name][row[4]] += row[2]
478 else:
479 obj_dict[obj_name] = {'RO': 0, 'RW': 0,
480 'Code': 0, 'Lib': lib_name, 'ZI': 0}
481 obj_dict[obj_name][row[4]] = row[2]
482
483 """
484 Transform the dictionary to a dictionary list in python and sort the
485 elements with total size.
486 """
487 for s in lib_dict.keys():
488 lib_list.append({'Name': s,
489 'RO': lib_dict[s]['RO'],
490 'RW': lib_dict[s]['RW'],
491 'Code': lib_dict[s]['Code'],
492 'ZI': lib_dict[s]['ZI']})
493 lib_list = sorted(lib_list,
494 key=lambda i: i['RO'] + i['Code'] + i['RW'] + i['ZI'],
495 reverse=True)
496 for s in obj_dict.keys():
497 obj_list.append({'Name': s,
498 'RO': obj_dict[s]['RO'],
499 'RW': obj_dict[s]['RW'],
500 'Code': obj_dict[s]['Code'],
501 'Lib': obj_dict[s]['Lib'],
502 'ZI': obj_dict[s]['ZI']})
503 obj_list = sorted(obj_list,
504 key=lambda i: i['RO'] + i['Code'] + i['RW'] + i['ZI'],
505 reverse=True)
506
507 def sum_data(data_list):
508 """
509 Calculate the sum of libraries or object files, and implement total
510 data line. It will be added into self.items.
511 """
512 ret = {'RO': 0, 'RW': 0, 'Code': 0, 'ZI': 0,
513 'Flash': 0, 'Ram': 0, 'Total': 0}
514 if len(data_list) > 0:
515 for s in data_list:
516 ret['Code'] += s['Code']
517 ret['RO'] += s['RO']
518 ret['RW'] += s['RW']
519 ret['ZI'] += s['ZI']
520 ret['Flash'] += s['Code'] + s['RO'] + s['RW']
521 ret['Ram'] += s['RW'] + s['ZI']
522 ret['Total'] = ret['Flash'] + ret['ZI']
523 self.items.append(self.__line2)
524 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
525 format("Summary",
526 ret['Flash'],
527 ret['Ram'],
528 ret['Code'],
529 ret['RO'],
530 ret['RW'],
531 ret['ZI'],
532 ret['Total']))
533 self.items.append(self.__line1)
534 return ret
535
536 def insert_column_line(title):
537 """
538 Quickly insert column line.
539 """
540 self.items.append(title)
541 self.items.append(self.__line2)
542 self.items.append(colums_name)
543 self.items.append(self.__line2)
544
545 def quick_insert_data_line(s):
546 """
547 Quickly insert a single data line.
548 """
549 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
550 format(s['Name'],
551 s['Code'] + s['RO'] + s['RW'],
552 s['RW'] + s['ZI'],
553 s['Code'],
554 s['RO'],
555 s['RW'],
556 s['ZI'],
557 s['Code'] + s['RO'] + s['RW'] + s['ZI']))
558 """
559 Dump library information.
560 """
561 self.items = [self.__line1]
562 insert_column_line("\t\t\t\t\t\t\tSection libraries")
563 for s in lib_list:
564 if s['Name'].find(".o") > 0:
565 exsit_no_lib_obj = True
566 else:
567 tmp_list.append(s)
568 quick_insert_data_line(s)
569 sum_data(tmp_list)
570
571 """
572 Dump object file information.
573 """
574 insert_column_line("\t\t\t\t\t\t\tSection object files")
575 for s in obj_list:
576 quick_insert_data_line(s)
577 ret = sum_data(obj_list)
578 total_flash_size, total_ram_size = ret['Flash'], ret['Ram']
579
580 """
581 Dump NOT-IN-LIBRARY object file information.
582 """
583 if exsit_no_lib_obj:
584 insert_column_line(
585 "\t\t\t\t\t\t\tSection NOT-IN-LIBRARY object files")
586 tmp_list = []
587 for s in lib_list:
588 if s['Name'].find(".o") > 0:
589 tmp_list.append(s)
590 quick_insert_data_line(s)
591 sum_data(tmp_list)
592
593 """
594 Insert the summary information at the top of this page.
595 """
596 cursor = self.__cur.execute(
597 "select * from Section WHERE name = '{}'".format(self.section_name))
598 for row in cursor:
599 self.items.insert(0, "Section Name :{}\tTotal Size :{}\tFlash : {}\tRAM : {:<6}\tPad size = {}".
600 format(self.section_name, row[1], total_flash_size, total_ram_size, row[3]))
601 break
602 self.items.insert(0, self.__line2)
603 self.items.insert(0, "\t\t\t\t\t\t\tSection information")
604 self.items.insert(0, self.__line1)
605
606 """
607 Dump detail information of the section.
608 """
609 index = 4 * ' '
610 self.items.append("\t\t\t\t\t\t\tDetail information")
611 self.items.append(self.__line2)
612 for s in lib_list:
613 self.items.append("{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".
614 format(s['Name'], s['Code'], s['RO'], s['RW'], s['ZI']))
615 for t in obj_list:
616 if t['Lib'] == s['Name']:
617 self.items.append(index + "{} Code Size = {} RO Data = {} RW Data = {} ZI Data = {}".format(
618 t['Name'], t['Code'], t['RO'], t['RW'], t['ZI']))
619 count = 0
620 cursor = self.__cur.execute("select * from Function WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' ORDER BY size DESC".
621 format(self.section_name,
622 s['Name'],
623 t['Name']))
624 for row in cursor:
625 if row and count == 0:
626 self.items.append(index * 2 + "Code size = {}".
627 format(t['Code']))
628 count = count + 1
629 self.items.append(index * 3 + "{:<6} {} ".
630 format(row[2], row[0]))
631
632 def get_certain_data(type_name, s, t):
633 count = 0
634 cursor = self.__cur.execute("select * from Data WHERE section = '{}' and lib_file = '{}' and obj_file = '{}' and type = '{}' ORDER BY size DESC".
635 format(self.section_name,
636 s['Name'],
637 t['Name'],
638 type_name))
639 for row in cursor:
640 if row and count == 0:
641 self.items.append(index * 2 + "{} Data = {}".
642 format(type_name, t[type_name]))
643 count = count + 1
644 self.items.append(index * 3 + "{:<6} {}".
645 format(row[2], row[0]))
646
647 get_certain_data('RO', s, t)
648 get_certain_data('RW', s, t)
649 get_certain_data('ZI', s, t)
650 self.items.append(self.__line2)
651
652 def draw_section_func(self):
653 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
654 format("Name",
655 "Section",
656 "Size",
657 "Address",
658 "Object File",
659 "Library")]
660 cursor = self.__cur.execute("select * from Function WHERE section = '{}' ORDER BY size DESC".
661 format(self.section_name))
662 for row in cursor:
663 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}{:<40}".
664 format(row[0], row[1], row[2], row[3], row[4], row[5]))
665
666 def draw_section_data(self):
667 self.items = ["{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
668 format("Name",
669 "Section",
670 "Size",
671 "Address",
672 "Type",
673 "Object File",
674 "Library")]
675
676 cursor = self.__cur.execute("select * from Data WHERE section = '{}' ORDER BY size DESC".
677 format(self.section_name))
678 for row in cursor:
679 data_name = row[0]
680 if len(data_name) >= 50:
681 data_name = data_name[:40] + "-->"
682 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<16}{:<40}{:<40}".
683 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
684
685 def __quick_append(self):
686 self.items.append(self.__line1)
687
688 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
689 format("Name",
690 "Section",
691 "Size",
692 "Type",
693 "Object File"))
694 self.items.append(self.__line2)
695
696 def __quick_append_data(self, cursor):
697 flag = False
698 for row in cursor:
699 if not flag:
700 self.__quick_append()
701 data_name = row[0]
702 if len(data_name) >= 50:
703 data_name = data_name[:40] + "-->"
704 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
705 format(data_name, row[1], row[2], row[4], row[5]))
706 flag = True
707
708 def draw_library_page(self):
709 self.items = ["{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
710 format("Name",
711 "Flash size",
712 "RAM size",
713 "Code",
714 "RO data",
715 "RW data",
716 "ZI data",
717 "Inc. data",
718 "Debug")]
719
720 cursor = self.__cur.execute(
721 "select * from Library ORDER BY flashsize DESC")
722 for row in cursor:
723 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
724 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
725
726 def draw_library_detail_page(self):
727 flag = False
728 """
729 Draw title.
730 """
731 self.items = [self.__line1, "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
732 format("Name",
733 "Flash size",
734 "RAM size",
735 "Code",
736 "RO data",
737 "RW data",
738 "ZI data",
739 "Inc. data"),
740 self.__line2]
741
742 cursor = self.__cur.execute("select * from Library WHERE name = '{}'".
743 format(self.library_name))
744 for row in cursor:
745 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
746 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]))
747 break
748
749 """
750 Draw object files.
751 """
752 self.items.append(self.__line1)
753 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
754 format("Name",
755 "Flash size",
756 "RAM size",
757 "Code",
758 "RO data",
759 "RW data",
760 "ZI data",
761 "Inc. data"))
762 self.items.append(self.__line2)
763
764 cursor = self.__cur.execute("select * from Object WHERE library = '{}' ORDER BY flashsize DESC".
765 format(self.library_name))
766 for row in cursor:
767 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
768 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
769
770 """
771 Draw functions.
772 """
773 cursor = self.__cur.execute("select * from Function WHERE lib_file = '{}' ORDER BY size DESC".
774 format(self.library_name))
775 for row in cursor:
776 if not flag:
777 self.__quick_append()
778 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
779 format(row[0], row[1], row[2], "Code", row[4]))
780 flag = True
781
782 """
783 Draw RO data.
784 """
785 cursor = self.__cur.execute("select * from Data WHERE type = 'RO' and lib_file = '{}' ORDER BY size DESC".
786 format(self.library_name))
787 self.__quick_append_data(cursor)
788
789 """
790 Draw RW data.
791 """
792 cursor = self.__cur.execute("select * from Data WHERE type = 'RW' and lib_file = '{}' ORDER BY size DESC".
793 format(self.library_name))
794 self.__quick_append_data(cursor)
795
796 """
797 Draw ZI data.
798 """
799 cursor = self.__cur.execute("select * from Data WHERE type = 'ZI' and lib_file = '{}' ORDER BY size DESC".
800 format(self.library_name))
801 self.__quick_append_data(cursor)
802 self.items.append(self.__line1)
803
804 def draw_obj_page(self):
805 self.items = ["{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
806 format("Name",
807 "Library",
808 "Flash size",
809 "RAM size",
810 "Code",
811 "RO data",
812 "RW data",
813 "ZI data",
814 "Inc. data",
815 "Debug")]
816 cursor = self.__cur.execute(
817 "select * from Object WHERE library = 'no library' ORDER BY flashsize DESC")
818 for row in cursor:
819 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
820 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
821 cursor = self.__cur.execute(
822 "select * from Object WHERE library != 'no library' ORDER BY flashsize DESC")
823 for row in cursor:
824 self.items.append("{:<50}{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
825 format(row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8], row[9]))
826
827 def draw_obj_detail_page(self):
828 flag = False
829 self.items = [self.__line1,
830 "{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
831 format("Name",
832 "Flash size",
833 "RAM size",
834 "Code",
835 "RO data",
836 "RW data",
837 "ZI data",
838 "Inc. data"),
839 self.__line2]
840
841 cursor = self.__cur.execute("select * from Object WHERE name = '{}'".
842 format(self.obj_file))
843 for row in cursor:
844 self.items.append("{:<50}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}{:<12}".
845 format(row[0], row[2], row[3], row[4], row[5], row[6], row[7], row[8]))
846 break
847
848 cursor = self.__cur.execute("select * from Function WHERE obj_file = '{}' ORDER BY size DESC".
849 format(self.obj_file))
850 for row in cursor:
851 if not flag:
852 self.__quick_append()
853 self.items.append("{:<50}{:<32}{:<10}{:<16}{:<40}".
854 format(row[0], row[1], row[2], "Code", row[4]))
855 flag = True
856
857 cursor = self.__cur.execute("select * from Data WHERE type = 'RO' and obj_file = '{}' ORDER BY size DESC".
858 format(self.obj_file))
859 self.__quick_append_data(cursor)
860
861 cursor = self.__cur.execute("select * from Data WHERE type = 'RW' and obj_file = '{}' ORDER BY size DESC".
862 format(self.obj_file))
863 self.__quick_append_data(cursor)
864
865 cursor = self.__cur.execute("select * from Data WHERE type = 'ZI' and obj_file = '{}' ORDER BY size DESC".
866 format(self.obj_file))
867 self.__quick_append_data(cursor)
868 self.items.append(self.__line1)
869
870 def draw_function_page(self, search_func):
871 self.items = []
872 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
873 format("Name",
874 "Section",
875 "Size",
876 "Address",
877 "Object File",
878 "Library"))
879 if search_func:
880 cursor = self.__cur.execute("select * from Function WHERE name LIKE '%{}%'".
881 format(search_func))
882 else:
883 cursor = self.__cur.execute(
884 "select * from Function ORDER BY size DESC")
885 for row in cursor:
886 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<40}{:<40}".
887 format(row[0], row[1], row[2], row[3], row[4], row[5]))
888
889 def draw_function_detail_page(self):
890 if self.obj_file:
891 cursor = self.__cur.execute("select * from Function WHERE name = '{}' and obj_file = '{}'".
892 format(self.function_name, self.obj_file))
893 else:
894 cursor = self.__cur.execute("select * from Function WHERE name = '{}'".
895 format(self.function_name))
896 for row in cursor:
897 self.items = ["=================================================",
898 "Name\t\t\t: {}".format(row[0]),
899 "Symbol type\t\t: Function",
900 "Section\t\t\t: {}".format(row[1]),
901 "Size\t\t\t: {}".format(row[2]),
902 "Base address\t\t: {}".format(row[3]),
903 "Object file\t\t: {}".format(row[4]),
904 "Library\t\t\t: {}".format(row[5]),
905 "================================================="]
906
907 def draw_data_page(self, search_data):
908 self.items = ["{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
909 format("Name",
910 "Section",
911 "Size",
912 "Address",
913 "Type",
914 "Object File",
915 "Library")]
916 if search_data:
917 cursor = self.__cur.execute("select * from Data WHERE name LIKE '%{}%'".
918 format(search_data))
919 else:
920 cursor = self.__cur.execute("select * from Data ORDER BY size DESC")
921 for row in cursor:
922 data_name = row[0]
923 if len(data_name) >= 50:
924 data_name = data_name[:40] + "-->"
925 self.items.append("{:<50}{:<50}{:<10}{:<16}{:<16}{:<40}{:<40}".
926 format(data_name, row[1], row[2], row[3], row[4], row[5], row[6]))
927
928 def draw_data_detail_page(self):
929 if self.obj_file:
930 cursor = self.__cur.execute("select * from Data WHERE name = '{}' and obj_file = '{}'".
931 format(self.data_name, self.obj_file))
932 else:
933 cursor = self.__cur.execute("select * from Data WHERE name = '{}'".
934 format(self.data_name))
935
936 for row in cursor:
937 self.items = ["=================================================",
938 "Name\t\t\t: {}".format(row[0]),
939 "Symbol type\t\t: {}".format(row[4]),
940 "Section\t\t\t: {}".format(row[1]),
941 "Size\t\t\t: {}".format(row[2]),
942 "Base address\t\t: {}".format(row[3]),
943 "Object file\t\t: {}".format(row[5]),
944 "Library\t\t\t: {}".format(row[6]),
945 "================================================="]
946
947 def run(self):
948 """
949 Continue running the TUI until get interrupted
950 """
951 self.__init_curses()
952 try:
953 self.__draw_page()
954 self.__input_stream()
955 except KeyboardInterrupt:
956 pass
957 finally:
958 curses.endwin()