| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | import os.path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  | from c_common import fsutil | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | import c_common.tables as _tables | 
					
						
							|  |  |  | import c_parser.info as _info | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BASE_COLUMNS = [ | 
					
						
							|  |  |  |     'filename', | 
					
						
							|  |  |  |     'funcname', | 
					
						
							|  |  |  |     'name', | 
					
						
							|  |  |  |     'kind', | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | END_COLUMNS = { | 
					
						
							|  |  |  |     'parsed': 'data', | 
					
						
							|  |  |  |     'decls': 'declaration', | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _get_columns(group, extra=None): | 
					
						
							|  |  |  |     return BASE_COLUMNS + list(extra or ()) + [END_COLUMNS[group]] | 
					
						
							|  |  |  |     #return [ | 
					
						
							|  |  |  |     #    *BASE_COLUMNS, | 
					
						
							|  |  |  |     #    *extra or (), | 
					
						
							|  |  |  |     #    END_COLUMNS[group], | 
					
						
							|  |  |  |     #] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | # high-level | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def read_parsed(infile): | 
					
						
							|  |  |  |     # XXX Support other formats than TSV? | 
					
						
							|  |  |  |     columns = _get_columns('parsed') | 
					
						
							|  |  |  |     for row in _tables.read_table(infile, columns, sep='\t', fix='-'): | 
					
						
							|  |  |  |         yield _info.ParsedItem.from_row(row, columns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def write_parsed(items, outfile): | 
					
						
							|  |  |  |     # XXX Support other formats than TSV? | 
					
						
							|  |  |  |     columns = _get_columns('parsed') | 
					
						
							|  |  |  |     rows = (item.as_row(columns) for item in items) | 
					
						
							|  |  |  |     _tables.write_table(outfile, columns, rows, sep='\t', fix='-') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def read_decls(infile, fmt=None): | 
					
						
							|  |  |  |     if fmt is None: | 
					
						
							|  |  |  |         fmt = _get_format(infile) | 
					
						
							|  |  |  |     read_all, _ = _get_format_handlers('decls', fmt) | 
					
						
							|  |  |  |     for decl, _ in read_all(infile): | 
					
						
							|  |  |  |         yield decl | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def write_decls(decls, outfile, fmt=None, *, backup=False): | 
					
						
							|  |  |  |     if fmt is None: | 
					
						
							|  |  |  |         fmt = _get_format(infile) | 
					
						
							|  |  |  |     _, write_all = _get_format_handlers('decls', fmt) | 
					
						
							|  |  |  |     write_all(decls, outfile, backup=backup) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############################# | 
					
						
							|  |  |  | # formats | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _get_format(file, default='tsv'): | 
					
						
							|  |  |  |     if isinstance(file, str): | 
					
						
							|  |  |  |         filename = file | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         filename = getattr(file, 'name', '') | 
					
						
							|  |  |  |     _, ext = os.path.splitext(filename) | 
					
						
							|  |  |  |     return ext[1:] if ext else default | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _get_format_handlers(group, fmt): | 
					
						
							|  |  |  |     # XXX Use a registry. | 
					
						
							|  |  |  |     if group != 'decls': | 
					
						
							|  |  |  |         raise NotImplementedError(group) | 
					
						
							|  |  |  |     if fmt == 'tsv': | 
					
						
							|  |  |  |         return (_iter_decls_tsv, _write_decls_tsv) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         raise NotImplementedError(fmt) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # tsv | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  | def iter_decls_tsv(infile, extracolumns=None, relroot=fsutil.USE_CWD): | 
					
						
							|  |  |  |     if relroot and relroot is not fsutil.USE_CWD: | 
					
						
							|  |  |  |         relroot = os.path.abspath(relroot) | 
					
						
							|  |  |  |     for info, extra in _iter_decls_tsv(infile, extracolumns): | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |         decl = _info.Declaration.from_row(info) | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |         decl = decl.fix_filename(relroot, formatted=False, fixroot=False) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |         yield decl, extra | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def write_decls_tsv(decls, outfile, extracolumns=None, *, | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |                     relroot=fsutil.USE_CWD, | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |                     **kwargs | 
					
						
							|  |  |  |                     ): | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |     if relroot and relroot is not fsutil.USE_CWD: | 
					
						
							|  |  |  |         relroot = os.path.abspath(relroot) | 
					
						
							|  |  |  |     decls = (d.fix_filename(relroot, fixroot=False) for d in decls) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |     # XXX Move the row rendering here. | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |     _write_decls_tsv(decls, outfile, extracolumns, kwargs) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  | def _iter_decls_tsv(infile, extracolumns=None): | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |     columns = _get_columns('decls', extracolumns) | 
					
						
							|  |  |  |     for row in _tables.read_table(infile, columns, sep='\t'): | 
					
						
							|  |  |  |         if extracolumns: | 
					
						
							|  |  |  |             declinfo = row[:4] + row[-1:] | 
					
						
							|  |  |  |             extra = row[4:-1] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             declinfo = row | 
					
						
							|  |  |  |             extra = None | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |         # XXX Use something like tables.fix_row() here. | 
					
						
							|  |  |  |         declinfo = [None if v == '-' else v | 
					
						
							|  |  |  |                     for v in declinfo] | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |         yield declinfo, extra | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  | def _write_decls_tsv(decls, outfile, extracolumns, kwargs): | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |     columns = _get_columns('decls', extracolumns) | 
					
						
							|  |  |  |     if extracolumns: | 
					
						
							|  |  |  |         def render_decl(decl): | 
					
						
							|  |  |  |             if type(row) is tuple: | 
					
						
							|  |  |  |                 decl, *extra = decl | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 extra = () | 
					
						
							|  |  |  |             extra += ('???',) * (len(extraColumns) - len(extra)) | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |             *row, declaration = _render_known_row(decl) | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |             row += extra + (declaration,) | 
					
						
							|  |  |  |             return row | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         render_decl = _render_known_decl | 
					
						
							|  |  |  |     _tables.write_table( | 
					
						
							|  |  |  |         outfile, | 
					
						
							|  |  |  |         header='\t'.join(columns), | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  |         rows=(render_decl(d) for d in decls), | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |         sep='\t', | 
					
						
							|  |  |  |         **kwargs | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-20 15:39:28 -07:00
										 |  |  | def _render_known_decl(decl, *, | 
					
						
							| 
									
										
										
										
											2020-10-22 18:42:51 -06:00
										 |  |  |                        # These match BASE_COLUMNS + END_COLUMNS[group]. | 
					
						
							|  |  |  |                        _columns = 'filename parent name kind data'.split(), | 
					
						
							|  |  |  |                        ): | 
					
						
							|  |  |  |     if not isinstance(decl, _info.Declaration): | 
					
						
							|  |  |  |         # e.g. Analyzed | 
					
						
							|  |  |  |         decl = decl.decl | 
					
						
							|  |  |  |     rowdata = decl.render_rowdata(_columns) | 
					
						
							|  |  |  |     return [rowdata[c] or '-' for c in _columns] | 
					
						
							|  |  |  |     # XXX | 
					
						
							|  |  |  |     #return _tables.fix_row(rowdata[c] for c in columns) |