1import os.path 2 3from c_common import fsutil 4import c_common.tables as _tables 5import c_parser.info as _info 6 7 8BASE_COLUMNS = [ 9 'filename', 10 'funcname', 11 'name', 12 'kind', 13] 14END_COLUMNS = { 15 'parsed': 'data', 16 'decls': 'declaration', 17} 18 19 20def _get_columns(group, extra=None): 21 return BASE_COLUMNS + list(extra or ()) + [END_COLUMNS[group]] 22 #return [ 23 # *BASE_COLUMNS, 24 # *extra or (), 25 # END_COLUMNS[group], 26 #] 27 28 29############################# 30# high-level 31 32def read_parsed(infile): 33 # XXX Support other formats than TSV? 34 columns = _get_columns('parsed') 35 for row in _tables.read_table(infile, columns, sep='\t', fix='-'): 36 yield _info.ParsedItem.from_row(row, columns) 37 38 39def write_parsed(items, outfile): 40 # XXX Support other formats than TSV? 41 columns = _get_columns('parsed') 42 rows = (item.as_row(columns) for item in items) 43 _tables.write_table(outfile, columns, rows, sep='\t', fix='-') 44 45 46def read_decls(infile, fmt=None): 47 if fmt is None: 48 fmt = _get_format(infile) 49 read_all, _ = _get_format_handlers('decls', fmt) 50 for decl, _ in read_all(infile): 51 yield decl 52 53 54def write_decls(decls, outfile, fmt=None, *, backup=False): 55 if fmt is None: 56 fmt = _get_format(infile) 57 _, write_all = _get_format_handlers('decls', fmt) 58 write_all(decls, outfile, backup=backup) 59 60 61############################# 62# formats 63 64def _get_format(file, default='tsv'): 65 if isinstance(file, str): 66 filename = file 67 else: 68 filename = getattr(file, 'name', '') 69 _, ext = os.path.splitext(filename) 70 return ext[1:] if ext else default 71 72 73def _get_format_handlers(group, fmt): 74 # XXX Use a registry. 75 if group != 'decls': 76 raise NotImplementedError(group) 77 if fmt == 'tsv': 78 return (_iter_decls_tsv, _write_decls_tsv) 79 else: 80 raise NotImplementedError(fmt) 81 82 83# tsv 84 85def iter_decls_tsv(infile, extracolumns=None, relroot=fsutil.USE_CWD): 86 if relroot and relroot is not fsutil.USE_CWD: 87 relroot = os.path.abspath(relroot) 88 for info, extra in _iter_decls_tsv(infile, extracolumns): 89 decl = _info.Declaration.from_row(info) 90 decl = decl.fix_filename(relroot, formatted=False, fixroot=False) 91 yield decl, extra 92 93 94def write_decls_tsv(decls, outfile, extracolumns=None, *, 95 relroot=fsutil.USE_CWD, 96 **kwargs 97 ): 98 if relroot and relroot is not fsutil.USE_CWD: 99 relroot = os.path.abspath(relroot) 100 decls = (d.fix_filename(relroot, fixroot=False) for d in decls) 101 # XXX Move the row rendering here. 102 _write_decls_tsv(decls, outfile, extracolumns, kwargs) 103 104 105def _iter_decls_tsv(infile, extracolumns=None): 106 columns = _get_columns('decls', extracolumns) 107 for row in _tables.read_table(infile, columns, sep='\t'): 108 if extracolumns: 109 declinfo = row[:4] + row[-1:] 110 extra = row[4:-1] 111 else: 112 declinfo = row 113 extra = None 114 # XXX Use something like tables.fix_row() here. 115 declinfo = [None if v == '-' else v 116 for v in declinfo] 117 yield declinfo, extra 118 119 120def _write_decls_tsv(decls, outfile, extracolumns, kwargs): 121 columns = _get_columns('decls', extracolumns) 122 if extracolumns: 123 def render_decl(decl): 124 if type(row) is tuple: 125 decl, *extra = decl 126 else: 127 extra = () 128 extra += ('???',) * (len(extraColumns) - len(extra)) 129 *row, declaration = _render_known_row(decl) 130 row += extra + (declaration,) 131 return row 132 else: 133 render_decl = _render_known_decl 134 _tables.write_table( 135 outfile, 136 header='\t'.join(columns), 137 rows=(render_decl(d) for d in decls), 138 sep='\t', 139 **kwargs 140 ) 141 142 143def _render_known_decl(decl, *, 144 # These match BASE_COLUMNS + END_COLUMNS[group]. 145 _columns = 'filename parent name kind data'.split(), 146 ): 147 if not isinstance(decl, _info.Declaration): 148 # e.g. Analyzed 149 decl = decl.decl 150 rowdata = decl.render_rowdata(_columns) 151 return [rowdata[c] or '-' for c in _columns] 152 # XXX 153 #return _tables.fix_row(rowdata[c] for c in columns) 154