1 /* btdt.c --- been there done that
2 
3    Copyright (C) 2010-2020 Thien-Thi Nguyen
4 
5    This file is part of GNU RCS.
6 
7    GNU RCS is free software: you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    GNU RCS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty
14    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15    See the GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "base.h"
22 #include <string.h>
23 #include <stdlib.h>
24 #include "stat-time.h"
25 #include "timespec.h"
26 #include "b-complain.h"
27 #include "b-divvy.h"
28 #include "b-esds.h"
29 #include "b-feph.h"
30 #include "b-fro.h"
31 #include "b-grok.h"
32 
33 /* This program serves as a collection of test-support commands
34    (to be invoked from the t??? files) for various components of
35    the RCS library.  */
36 
37 struct top *top;
38 
39 exiting void
bad_args(char const * argv0)40 bad_args (char const *argv0)
41 {
42   fprintf (stderr, "%s: bad args (try %s --help)\n",
43            argv0, PROGRAM (invoke));
44   _Exit (EXIT_FAILURE);
45 }
46 
47 #define MORE "\n\t\t"
48 
49 
50 /* ‘getoldkeys’ */
51 
52 /* Print the keyword values found.  */
53 
54 char const getoldkeys_usage[] =
55   "WORKING-FILE";
56 
57 void
getoldkeys_spew(char const * what,char * s)58 getoldkeys_spew (char const *what, char *s)
59 {
60   if (s)
61     printf ("%s: %zu \"%s\"\n", what, strlen (s), s);
62 }
63 
64 int
getoldkeys_do_it(int argc,char * argv[VLA_ELEMS (argc)])65 getoldkeys_do_it (int argc, char *argv[VLA_ELEMS (argc)])
66 {
67   if (2 > argc)
68     bad_args (argv[0]);
69 
70   MANI (filename) = argv[1];
71   getoldkeys (NULL);
72   printf ("valid: %s\n", PREV (valid) ? "true" : "false");
73   getoldkeys_spew ("revno", PREV (rev));
74   getoldkeys_spew ("date", PREV (date));
75   getoldkeys_spew ("author", PREV (author));
76   getoldkeys_spew ("name", PREV (name));
77   getoldkeys_spew ("state", PREV (state));
78   return EXIT_SUCCESS;
79 }
80 
81 
82 /* ‘grok_all’ */
83 
84 /* Parse an RCS file and display different aspects of the result.  */
85 
86 char const grok_usage[] =
87   "RCS-FILE [ASPECT...]"
88   MORE "where ASPECT is one of:"
89   MORE "  edits-order";
90 
91 int
grok_do_it(int argc,char * argv[VLA_ELEMS (argc)])92 grok_do_it (int argc, char *argv[VLA_ELEMS (argc)])
93 {
94   int i;
95   struct fro *f;
96 
97   REPO (filename) = argv[1];            /* FIXME: for ‘RERR’ */
98   if (! (f = fro_open (argv[1], "r", NULL)))
99     RERR ("cannot open %s", argv[1]);
100   if (! (REPO (r) = grok_all (SINGLE, f)))
101     RERR ("grok_all failed for %s", argv[1]);
102 
103   for (i = 2; i < argc; i++)
104     {
105       struct delta *d;
106       char const *aspect = argv[i];
107 
108       printf ("%s:\n", aspect);
109       if (STR_SAME ("edits-order", aspect))
110         for (struct wlink *ls = GROK (deltas); ls; ls = ls->next)
111           {
112             d = ls->entry;
113             printf ("%s\n", d->num);
114           }
115       else
116         bad_args (argv[0]);
117     }
118 
119   return EXIT_SUCCESS;
120 }
121 
122 
123 /* xorlf */
124 
125 /* XOR stdin with LF (aka '\n', 012, 0xA) to stdout.  */
126 
127 char const xorlf_usage[] =
128   "";
129 
130 int
xorlf_do_it(int argc,char * argv[VLA_ELEMS (argc)]RCS_UNUSED)131 xorlf_do_it (int argc, char *argv[VLA_ELEMS (argc)] RCS_UNUSED)
132 {
133   int c;
134 
135   while (EOF != (c = getchar ()))
136     putchar (c ^ 012);
137   return EXIT_SUCCESS;
138 }
139 
140 
141 /* mtimecmp */
142 
143 /* Consider mtime of both FILE1 and FILE2 as M1 and M2.
144    If M1 < M2, display "-1" to stdout.
145    If M1 = M2, display "0" to stdout.
146    If M1 > M2, display "1" to stdout.  */
147 
148 char const mtimecmp_usage[] =
149   "FILE1 FILE2";
150 
151 struct timespec
mtimecmp_grok(char const * filename)152 mtimecmp_grok (char const *filename)
153 {
154   struct stat st;
155 
156   if (PROB (stat (filename, &st)))
157     {
158       fprintf (stderr, "mtimecmp: could not stat %s\n",
159                filename);
160       _Exit (EXIT_FAILURE);
161     }
162 
163   return get_stat_mtime (&st);
164 }
165 
166 int
mtimecmp_do_it(int argc,char * argv[VLA_ELEMS (argc)])167 mtimecmp_do_it (int argc, char *argv[VLA_ELEMS (argc)])
168 {
169   struct timespec m1, m2;
170   long int sign;
171 
172   if (3 > argc)
173     bad_args (argv[0]);
174 
175   m1 = mtimecmp_grok (argv[1]);
176   m2 = mtimecmp_grok (argv[2]);
177 
178   sign = timespec_cmp (m1, m2);
179   if (0 > sign) sign = -1;
180   if (0 < sign) sign =  1;
181 
182   printf ("%ld\n", sign);
183   return EXIT_SUCCESS;
184 }
185 
186 
187 typedef int (main_t) (int argc, char *argv[VLA_ELEMS (argc)]);
188 
189 struct yeah
190 {
191   char const *component;
192   char const *usage;
193   main_t *whatever;
194   bool scram;
195 };
196 
197 #define YEAH(comp,out)  { #comp, comp ## _usage, comp ## _do_it, out }
198 
199 struct yeah yeah[] =
200   {
201     YEAH (getoldkeys,   true),
202     YEAH (grok,         true),
203     YEAH (xorlf,        true),
204     YEAH (mtimecmp,     true),
205   };
206 
207 #define NYEAH  (sizeof (yeah) / sizeof (struct yeah))
208 
209 int
main(int argc,char * argv[VLA_ELEMS (argc)])210 main (int argc, char *argv[VLA_ELEMS (argc)])
211 {
212   char const *me = "btdt";
213 
214   if (STR_SAME ("--version", argv[1]))
215     {
216       printf ("btdt (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
217       printf ("Copyright (C) 2010-2020 Thien-Thi Nguyen\n");
218       printf ("License GPLv3+; GNU GPL version 3 or later"
219               " <http://gnu.org/licenses/gpl.html>\n\n");
220       argv[1] = "--help";
221       /* fall through */
222     }
223 
224   if (2 > argc || STR_SAME ("--help", argv[1]))
225     {
226       printf ("Usage: %s COMPONENT [ARG...]\n", me);
227       for (size_t i = 0; i < NYEAH; i++)
228         printf ("- %-10s %s\n", yeah[i].component, yeah[i].usage);
229       printf ("\n(Read the source for details.)\n");
230       return EXIT_SUCCESS;
231     }
232 
233   for (size_t i = 0; i < NYEAH; i++)
234     if (STR_SAME (yeah[i].component, argv[1]))
235       {
236         int exitstatus;
237         const struct program program =
238           {
239             .invoke = me,
240             .name  = argv[1],
241             .tyag = (yeah[i].scram
242                      ? TYAG_IMMEDIATE
243                      : BOG_ZONK)
244           };
245 
246         gnurcs_init (&program);
247         exitstatus = yeah[i].whatever (argc - 1, argv + 1);
248         gnurcs_goodbye ();
249         return exitstatus;
250       }
251 
252   fprintf (stderr, "%s: bad component (try --help): %s\n", me, argv[1]);
253   return EXIT_FAILURE;
254 }
255 
256 /* btdt.c ends here */
257