1// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2// -*- Mode: C++ -*- 3// 4// Copyright (C) 2013-2022 Red Hat, Inc. 5// 6// Author: Dodji Seketeli 7 8/// @file 9/// 10/// This file implements a simple command line utility for 11/// interactively testing the diff2 algorithms declared and defined in 12/// abg-diff-utils.{h,cc} 13/// 14/// The resulting binary name is testdiff2. Run it to see a help message 15/// showing you how to use it. 16 17#include <cstring> 18#include <iostream> 19#include "abg-diff-utils.h" 20 21using std::cout; 22using std::string; 23 24using abigail::diff_utils::ses_len; 25using abigail::diff_utils::point; 26using abigail::diff_utils::snake; 27using abigail::diff_utils::compute_middle_snake; 28using abigail::diff_utils::print_snake; 29using abigail::diff_utils::compute_lcs; 30using abigail::diff_utils::edit_script; 31using abigail::diff_utils::compute_ses; 32using abigail::diff_utils::display_edit_script; 33 34struct options 35{ 36 bool show_help; 37 bool ses_len; 38 bool reverse; 39 bool middle_snake; 40 bool lcs; 41 bool ses; 42 const char* str1; 43 const char* str2; 44 45 options() 46 : show_help(false), 47 ses_len(false), 48 reverse(false), 49 middle_snake(false), 50 lcs(false), 51 ses(false), 52 str1(0), 53 str2(0) 54 {} 55};// end struct options 56 57static void 58show_help(const string& progname) 59{ 60 cout << "usage: " << progname << " [options] str1 str2\n" 61 << "where [options] can be:\n" 62 << "--seslen print the length of the SES of the two strings\n" 63 << "--reverse compute the d-paths in reverse order when applicable\n" 64 << "--middle-snake display middle snake & length of SES\n" 65 << "--lcs display the longest common subsequence\n" 66 << "--ses display the shortest edit script transforming str1 into str2\n"; 67} 68 69static void 70parse_command_line(int argc, char* argv[], options &opts) 71{ 72 if (argc < 3) 73 { 74 opts.show_help = true; 75 return; 76 } 77 78 for (int i = 1; i < argc; ++i) 79 { 80 if (argv[i][0] != '-') 81 { 82 if (!opts.str1) 83 opts.str1 = argv[i]; 84 else if (!opts.str2) 85 opts.str2 = argv[i]; 86 else 87 { 88 opts.show_help = true; 89 return; 90 } 91 } 92 else if (strcmp(argv[i], "--seslen") == 0) 93 opts.ses_len = true; 94 else if (strcmp(argv[i], "--reverse") == 0) 95 opts.reverse = true; 96 else if (strcmp(argv[i], "--middle-snake") == 0) 97 opts.middle_snake = true; 98 else if (strcmp(argv[i], "--lcs") == 0) 99 opts.lcs = true; 100 else if (strcmp(argv[i], "--ses") == 0) 101 opts.ses = true; 102 else 103 opts.show_help = true; 104 } 105} 106 107int 108main(int argc, char*argv[]) 109{ 110 options opts; 111 parse_command_line(argc, argv, opts); 112 113 if (opts.show_help) 114 { 115 show_help(argv[0]); 116 return -1; 117 } 118 119 if (opts.ses_len) 120 { 121 int len = ses_len(opts.str1, opts.str2, opts.reverse); 122 cout << len << "\n"; 123 return 0; 124 } 125 126 if (opts.middle_snake) 127 { 128 int ses_len = 0; 129 snake s; 130 if (compute_middle_snake(opts.str1, opts.str2, 131 s, ses_len)) 132 { 133 print_snake(opts.str1, opts.str2, s, cout); 134 cout << "ses len: " << ses_len << "\n"; 135 } 136 return 0; 137 } 138 139 if (opts.lcs) 140 { 141 string lcs; 142 int ses_len = 0; 143 compute_lcs(opts.str1, opts.str2, ses_len, lcs); 144 cout << "lcs: " << lcs << "\n" 145 << "ses len: " << ses_len << "\n"; 146 return 0; 147 } 148 149 if (opts.ses) 150 { 151 edit_script ses; 152 compute_ses(opts.str1, opts.str2, ses); 153 display_edit_script(ses, opts.str1, opts.str2, cout); 154 return 0; 155 } 156 157 return 0; 158} 159