Tool: Update some new features and refinements

 - Support name the output database file.
 - Support input specific name database file.
 - Fix the defect that delete all database file in the path.
 - UI option and terminal options are conflicting now.
 - Terminal messages are reversed, summary info shows at last.
 - Support sort messages in terminal mode.
 - Update help message and document.
 - Other code and structure refinements.

Signed-off-by: Jianliang Shen <jianliang.shen@arm.com>
Change-Id: I597f05bebc4f20d316f400ed3d099bd9dbbd972a
diff --git a/code-size-analyze-tool/code_size_analyze.py b/code-size-analyze-tool/code_size_analyze.py
index 4aa6763..ef914f2 100644
--- a/code-size-analyze-tool/code_size_analyze.py
+++ b/code-size-analyze-tool/code_size_analyze.py
@@ -8,94 +8,168 @@
 import argparse
 import os
 import sys
+import glob
 sys.path.append("src")
 from ui import UI
 from sq import SQ
 
-none_databse = "Cannot find database file! Please use this command to create \
-databse:\n\n\tpython3 code_size_analyze.py -i <map file path> --gnuarm/--armcc\n"
+none_databse = "Cannot find database {}! Please use this command to create \
+databse:\n\n\tpython3 code_size_analyze.py --map <map file path> \
+--gnuarm/--armcc --db {}\n"
+
+def reverse_terminal_text(items):
+    line1 = "─" * 128
+    tmp, ret = [], []
+    for x in items:
+        if x == line1:
+            ret.append(tmp)
+            tmp = []
+        tmp.append(x)
+    items = []
+    for i in range(len(ret) - 1, -1, -1):
+        items.extend(ret[i])
+    items.append(line1)
+    return items
 
 def main(args):
-    """
-    It is required to input only one of '--gnuarm' and '--armcc'.
-    """
-    if (args.gnuarm_compiler and args.armclang_compiler) or \
-        (not args.gnuarm_compiler and not args.armclang_compiler):
-        print("Error: Need \'--gnuarm\' or \'--armcc\'")
-        exit(0)
-
+    map_file, db_file = "", ""
+    if args.file_input.find(".map") >= 0:
+        map_file = args.file_input
+    else:
+        db_file = args.file_input
     """
     Class 'sq' is to create a sqlite3 database from map file of compiler.
     """
-    if args.map_file_input:
+    if map_file:
+        if not args.gnuarm_compiler and not args.armclang_compiler:
+            print("Error: Need --gnuarm or --armcc to create database")
+            exit(0)
+        if os.path.exists(args.db_name):
+            for infile in glob.glob(os.path.join(os.getcwd(), args.db_name)):
+                os.remove(infile)
         sq = SQ()
         sq.gnuarm = True if args.gnuarm_compiler else False
         sq.armcc = True if args.armclang_compiler else False
-        sq.file_path = args.map_file_input
+        sq.map_file = map_file
+        sq.db_name = args.db_name
         sq.update()
 
-    if os.path.exists('data.db'):
+    if (db_file and os.path.exists(db_file)) or (map_file and os.path.exists(args.db_name)):
         """
         Class 'ui' is to show the ui in terminal or export plaintext.
         """
         ui = UI()
         ui.gnuarm = True if args.gnuarm_compiler else False
         ui.armcc = True if args.armclang_compiler else False
-        output = ""
+        if db_file:
+            ui.db_file = db_file
+        if map_file:
+            ui.db_file = args.db_name
+        ui.open_db()
+        if args.sort_by_size:
+            ui.sort = "size"
+        if args.sort_by_name:
+            ui.sort = "name"
+        if args.sort_by_obj:
+            ui.sort = "obj_file"
+        if args.sort_by_lib:
+            ui.sort = "lib_file"
+        if args.sort_by_sec:
+            ui.sort = "section"
+
+        if args.desc:
+            ui.order = "DESC"
+        if args.asc:
+            ui.order = "ASC"
+
         if args.ui_show:
+            if args.sort_by_name or args.sort_by_obj or args.sort_by_lib or args.sort_by_sec:
+                print("UI mode cannot support sort. Use it in terminal mode.")
+                exit(0)
             ui.run()
-        else:
-            if args.all:
-                ui.draw_summary_page()
 
-            if args.list_function:
-                ui.draw_function_page("")
+        if args.all:
+            ui.draw_summary_page()
 
-            if args.function_name:
-                ui.draw_function_page(args.function_name)
+        if args.list_function:
+            ui.draw_function_page("")
 
-            if args.dump_function_name:
-                ui.function_name = args.dump_function_name
-                ui.draw_function_detail_page()
+        if args.function_name:
+            ui.draw_function_page(args.function_name)
 
-            if args.list_data:
-                ui.draw_data_page("")
+        if args.dump_function_name:
+            ui.function_name = args.dump_function_name
+            ui.draw_function_detail_page()
 
-            if args.data_name:
-                ui.draw_data_page(args.data_name)
+        if args.list_data:
+              ui.draw_data_page("")
 
-            if args.dump_data_name:
-                ui.data_name = args.dump_data_name
-                ui.draw_data_detail_page()
+        if args.data_name:
+            ui.draw_data_page(args.data_name)
 
-            if args.list_obj:
-                ui.draw_obj_page()
+        if args.dump_data_name:
+            ui.data_name = args.dump_data_name
+            ui.draw_data_detail_page()
 
-            if args.obj_name:
-                ui.obj_file = args.obj_name
-                ui.draw_obj_detail_page()
+        if args.list_obj:
+            if args.sort_by_obj:
+                ui.sort = "name"
+            if args.sort_by_sec:
+                print("Object files cannot sort by this option")
+                exit(0)
+            ui.draw_obj_page()
 
-            if args.list_library:
-                ui.draw_library_page()
+        if args.obj_name:
+            ui.obj_file = args.obj_name
+            ui.draw_obj_detail_page()
+            ui.items = reverse_terminal_text(ui.items)
 
-            if args.library_name:
-                ui.library_name = args.library_name
-                ui.draw_library_detail_page()
+        if args.list_library:
+            if args.sort_by_lib:
+                ui.sort = "name"
+            if args.sort_by_obj or args.sort_by_sec:
+                print("Libraries cannot sort by this option")
+                exit(0)
+            ui.draw_library_page()
 
-            if args.list_section:
-                ui.draw_section_page()
+        if args.library_name:
+            if args.sort_by_sec or args.sort_by_obj:
+                print("Library dump cannot sort by this option")
+                exit(0)
+            ui.library_name = args.library_name
+            ui.draw_library_detail_page()
+            ui.items = reverse_terminal_text(ui.items)
 
-            if args.section_name:
-                ui.section_name = args.section_name
-                ui.draw_section_lib()
+        if args.list_section:
+            if args.sort_by_sec:
+                ui.sort = "name"
+            if args.sort_by_lib or args.sort_by_obj:
+                print("Sections cannot sort by this option")
+                exit(0)
+            ui.draw_section_page()
 
-            output = ui.items
-            if output:
-                for s in output:
-                    print(s)
-        ui.con.close()
+        if args.section_name:
+            if args.sort_by_name or args.sort_by_obj or args.sort_by_lib or args.sort_by_sec:
+                print("Section dump cannot support sort.")
+                exit(0)
+            ui.section_name = args.section_name
+            ui.draw_section_lib()
+            ui.items = reverse_terminal_text(ui.items)
+
+        if "─" * 128 not in ui.items and "-" * 128 not in ui.items and ui.items:
+            max_len = 0
+            for x in ui.items:
+                max_len = max(max_len, len(x))
+            ui.items.insert(1, "-" * max_len)
+            ui.items.insert(0, "─" * max_len)
+            ui.items.append("─" * max_len)
+
+        if ui.items and not args.ui_show:
+            for s in ui.items:
+                print(s)
+
     else:
-        print(none_databse)
+        print(none_databse.format(db_file, db_file))
 
 def parse_args():
     """
@@ -103,66 +177,120 @@
     """
     parser = argparse.ArgumentParser()
 
-    parser.add_argument('-i', '--input',
-                        dest='map_file_input',
-                        help='map file path <path>/tfm_s.map')
-    parser.add_argument('-u', '--ui',
-                        dest='ui_show',
-                        action='store_true',
-                        help='show UI')
-    parser.add_argument('--gnuarm',
-                        dest='gnuarm_compiler',
-                        action='store_true',
-                        help='gnuarm map file input')
-    parser.add_argument('--armcc',
-                        dest='armclang_compiler',
-                        action='store_true',
-                        help='armclang map file input')
-    parser.add_argument('-a', '--all',
-                        dest='all',
-                        action='store_true',
-                        help='show total')
-    parser.add_argument('-s', '--list_section',
-                        dest='list_section',
-                        action='store_true',
-                        help='list section')
-    parser.add_argument('-l', '--list_library',
-                        dest='list_library',
-                        action='store_true',
-                        help='list library')
-    parser.add_argument('-o', '--list_obj',
-                        dest='list_obj',
-                        action='store_true',
-                        help='list object file')
-    parser.add_argument('-f', '--list_function',
-                        dest='list_function',
-                        action='store_true',
-                        help='list function')
-    parser.add_argument('-d', '--list_data',
-                        dest='list_data',
-                        action='store_true',
-                        help='list data')
-    parser.add_argument('--dump_section',
-                        dest='section_name',
-                        help='dump section')
-    parser.add_argument('--dump_library',
-                        dest='library_name',
-                        help='dump library')
-    parser.add_argument('--dump_obj',
-                        dest='obj_name',
-                        help='dump object file')
-    parser.add_argument('--dump_function',
-                        dest='dump_function_name',
-                        help='dump function')
-    parser.add_argument('--dump_data',
-                        dest='dump_data_name',
-                        help='dump data')
-    parser.add_argument('--search_func',
-                        dest='function_name',
-                        help='search function')
-    parser.add_argument('--search_data',
-                        dest='data_name',
-                        help='search data')
+    compiler_group = parser.add_mutually_exclusive_group()
+    compiler_group.add_argument('--gnuarm',
+                                dest='gnuarm_compiler',
+                                action='store_true',
+                                help='GNUARM model')
+    compiler_group.add_argument('--armcc',
+                                dest='armclang_compiler',
+                                action='store_true',
+                                help='ARMCLANG model')
+
+    parser.add_argument('file_input', help='map or database file')
+    parser.add_argument('--db-name',
+                        dest='db_name',
+                        metavar='<data.db>',
+                        default='data.db',
+                        help='database name to save')
+
+    terminal_opt = parser.add_mutually_exclusive_group()
+    terminal_opt.add_argument('-u', '--ui',
+                              dest='ui_show',
+                              action='store_true',
+                              help='start UI to analyze')
+    terminal_opt.add_argument('-S', '--Summary',
+                              dest='all',
+                              action='store_true',
+                              help='show summary message')
+    terminal_opt.add_argument('-s', '--list-section',
+                              dest='list_section',
+                              action='store_true',
+                              help='list section')
+    terminal_opt.add_argument('-l', '--list-library',
+                              dest='list_library',
+                              action='store_true',
+                              help='list library')
+    terminal_opt.add_argument('-o', '--list-obj',
+                              dest='list_obj',
+                              action='store_true',
+                              help='list object file')
+    terminal_opt.add_argument('-f', '--list-function',
+                              dest='list_function',
+                              action='store_true',
+                              help='list function')
+    terminal_opt.add_argument('-d', '--list-data',
+                              dest='list_data',
+                              action='store_true',
+                              help='list data')
+    terminal_opt.add_argument('--dump-sec',
+                              dest='section_name',
+                              metavar='<sec>',
+                              help='dump section')
+    terminal_opt.add_argument('--dump-lib',
+                              dest='library_name',
+                              metavar='<lib>',
+                              help='dump library')
+    terminal_opt.add_argument('--dump-obj',
+                              dest='obj_name',
+                              metavar='<obj>',
+                              help='dump object file')
+    terminal_opt.add_argument('--dump-func',
+                              dest='dump_function_name',
+                              metavar='<func>',
+                              help='dump function')
+    terminal_opt.add_argument('--dump-data',
+                              dest='dump_data_name',
+                              metavar='<data>',
+                              help='dump data')
+    terminal_opt.add_argument('--search-func',
+                              dest='function_name',
+                              metavar='<func>',
+                              help='search function')
+    terminal_opt.add_argument('--search-data',
+                              dest='data_name',
+                              metavar='<data>',
+                              help='search data')
+
+    sort_opt = parser.add_mutually_exclusive_group()
+    sort_opt.add_argument('--sort-by-size',
+                          dest='sort_by_size',
+                          action='store_true',
+                          default=True,
+                          help='list by size order')
+    sort_opt.add_argument('--sort-by-name',
+                          dest='sort_by_name',
+                          action='store_true',
+                          default=False,
+                          help='list by name order')
+    sort_opt.add_argument('--sort-by-obj',
+                          dest='sort_by_obj',
+                          action='store_true',
+                          default=False,
+                          help='list by object file name order')
+    sort_opt.add_argument('--sort-by-lib',
+                          dest='sort_by_lib',
+                          action='store_true',
+                          default=False,
+                          help='list by library file name order')
+    sort_opt.add_argument('--sort-by-sec',
+                          dest='sort_by_sec',
+                          action='store_true',
+                          default=False,
+                          help='list by section name order')
+
+    sort_ord = parser.add_mutually_exclusive_group()
+    sort_ord.add_argument('--desc',
+                          dest='desc',
+                          action='store_true',
+                          default=True,
+                          help='sort with desc order')
+    sort_ord.add_argument('--asc',
+                          dest='asc',
+                          action='store_true',
+                          default=False,
+                          help='sort with asc order')
+
     args = parser.parse_args()
     return args