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
21 using std::cout;
22 using std::string;
23
24 using abigail::diff_utils::ses_len;
25 using abigail::diff_utils::point;
26 using abigail::diff_utils::snake;
27 using abigail::diff_utils::compute_middle_snake;
28 using abigail::diff_utils::print_snake;
29 using abigail::diff_utils::compute_lcs;
30 using abigail::diff_utils::edit_script;
31 using abigail::diff_utils::compute_ses;
32 using abigail::diff_utils::display_edit_script;
33
34 struct 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
optionsoptions45 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
57 static void
show_help(const string & progname)58 show_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
69 static void
parse_command_line(int argc,char * argv[],options & opts)70 parse_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
107 int
main(int argc,char * argv[])108 main(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