18cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd/**
28cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @file symbol_sort.cpp
38cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * Sorting symbols
48cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
58cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Copyright 2002, 2003 OProfile authors
68cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @remark Read the file COPYING
78cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd *
88cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author Philippe Elie
98cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd * @author John Levon
108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd */
118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "symbol_sort.h"
138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "symbol_functors.h"
148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "name_storage.h"
168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include "op_exception.h"
178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <algorithm>
198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd#include <sstream>
208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddusing namespace std;
228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddnamespace {
248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool long_filenames;
268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint image_compare(image_name_id l, image_name_id r)
288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (long_filenames)
308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return image_names.name(l).compare(image_names.name(r));
318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return image_names.basename(l).compare(image_names.basename(r));
328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint debug_compare(debug_name_id l, debug_name_id r)
368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (long_filenames)
388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return debug_names.name(l).compare(debug_names.name(r));
398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return debug_names.basename(l).compare(debug_names.basename(r));
408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddint compare_by(sort_options::sort_order order,
448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd               symbol_entry const & lhs, symbol_entry const & rhs)
458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	switch (order) {
478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::sample:
488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (lhs.sample.counts[0] < rhs.sample.counts[0])
498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return 1;
508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (lhs.sample.counts[0] > rhs.sample.counts[0])
518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return -1;
528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return 0;
538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::symbol:
558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return symbol_names.demangle(lhs.name).compare(
568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				symbol_names.demangle(rhs.name));
578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::image:
598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return image_compare(lhs.image_name, rhs.image_name);
608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::app_name:
628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return image_compare(lhs.app_name, rhs.app_name);
638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::vma:
658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (lhs.sample.vma < rhs.sample.vma)
668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return -1;
678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (lhs.sample.vma > rhs.sample.vma)
688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				return 1;
698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return 0;
708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		case sort_options::debug: {
728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			file_location const & f1 = lhs.sample.file_loc;
738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			file_location const & f2 = rhs.sample.file_loc;
748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			int ret = debug_compare(f1.filename, f2.filename);
758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			if (ret == 0)
768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				ret = f1.linenr - f2.linenr;
778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return ret;
788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		default: {
818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// static_cast<> to shut up g++ 2.91.66 which warn
828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			// about ambiguity between <<(int) and <<(long int)
838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ostringstream os;
848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			os << "compare_by(): unknown sort option: "
858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			   << static_cast<int>(order) << endl;
868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			throw op_fatal_error(os.str());
878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		}
888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return 0;
918cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
928cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
938cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
948cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddstruct symbol_compare {
958cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	symbol_compare(vector<sort_options::sort_order> const & order,
968cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	               bool reverse)
978cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		: compare_order(order), reverse_sort(reverse) {}
988cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
998cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool operator()(symbol_entry const * lhs,
1008cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			symbol_entry const * rhs) const {
1018cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		return operator()(*lhs, *rhs);
1028cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1038cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1048cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool operator()(symbol_entry const & lhs,
1058cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			symbol_entry const & rhs) const;
1068cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1078cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddprotected:
1088cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<sort_options::sort_order> const & compare_order;
1098cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	bool reverse_sort;
1108cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd};
1118cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1128cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1138cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddbool symbol_compare::operator()(symbol_entry const & lhs,
1148cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd				symbol_entry const & rhs) const
1158cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1168cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (size_t i = 0; i < compare_order.size(); ++i) {
1178cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		int ret = compare_by(compare_order[i], lhs, rhs);
1188cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1198cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (reverse_sort)
1208cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			ret = -ret;
1218cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (ret != 0)
1228cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			return ret < 0;
1238cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1248cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	return false;
1258cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1268cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1278cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1288cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd} // anonymous namespace
1298cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1308cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1318cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid sort_options::
1328cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsort(symbol_collection & syms, bool reverse_sort, bool lf) const
1338cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1348cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	long_filenames = lf;
1358cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1368cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<sort_order> sort_option(options);
1378cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
1388cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (find(sort_option.begin(), sort_option.end(), cur) ==
1398cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		    sort_option.end())
1408cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			sort_option.push_back(cur);
1418cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1428cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1438cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stable_sort(syms.begin(), syms.end(),
1448cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	            symbol_compare(sort_option, reverse_sort));
1458cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1468cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1478cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1488cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid sort_options::
1498cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddsort(diff_collection & syms, bool reverse_sort, bool lf) const
1508cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1518cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	long_filenames = lf;
1528cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1538cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	vector<sort_order> sort_option(options);
1548cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	for (sort_order cur = first; cur != last; cur = sort_order(cur + 1)) {
1558cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		if (find(sort_option.begin(), sort_option.end(), cur) ==
1568cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		    sort_option.end())
1578cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd			sort_option.push_back(cur);
1588cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1598cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1608cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	stable_sort(syms.begin(), syms.end(),
1618cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	            symbol_compare(sort_option, reverse_sort));
1628cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1638cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1648cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1658cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid sort_options::add_sort_option(string const & name)
1668cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1678cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	if (name == "vma") {
1688cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(vma);
1698cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (name == "sample") {
1708cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(sample);
1718cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (name == "symbol") {
1728cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(symbol);
1738cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (name == "debug") {
1748cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(debug);
1758cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (name == "image") {
1768cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(image);
1778cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else if (name == "app-name") {
1788cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		options.push_back(app_name);
1798cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	} else {
1808cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		ostringstream os;
1818cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		os << "unknown sort option: " << name << endl;
1828cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd		throw op_fatal_error(os.str());
1838cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	}
1848cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
1858cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1868cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd
1878cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Doddvoid sort_options::add_sort_option(sort_options::sort_order order)
1888cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd{
1898cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd	options.push_back(order);
1908cfa702f803c5ef6a2b062a489a1b2cf66b45b5eMike Dodd}
191