]> git.draconx.ca Git - upkg.git/blob - test/decodeindex.c
Stop using gnulib's flexmember module.
[upkg.git] / test / decodeindex.c
1 /*
2  * Tool for decoding compact index values for testing.
3  * Copyright © 2012, 2022 Nick Bowler
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <getopt.h>
23
24 #include <upkg.h>
25 #include "common.h"
26
27 #define PROGNAME "decodeindex"
28 static const char *progname = PROGNAME;
29 static const char sopts[] = "VH";
30 static const struct option lopts[] = {
31         { "version", 0, NULL, 'V' },
32         { "help",    0, NULL, 'H' },
33         { 0 }
34 };
35
36 static void print_usage(FILE *f)
37 {
38         fprintf(f, "Usage: %s [options] index [index ...]\n", progname);
39 }
40
41 static void print_help(void)
42 {
43         print_usage(stdout);
44         test_print_options(lopts);
45 }
46
47 static void print_bytes(FILE *f, int indent, void *buf, size_t n)
48 {
49         fprintf(f, "%*s", indent, "");
50
51         if (n == 0) {
52                 fprintf(f, "(empty)\n");
53                 return;
54         }
55
56         for (size_t i = 0; i < n; i++)
57                 fprintf(f, "%*s%.2hhx", i != 0, "", ((unsigned char *)buf)[i]);
58         putc('\n', f);
59 }
60
61 static int print_index(const char *hex)
62 {
63         unsigned char buf[32];
64         long index = 0;
65         size_t n, rc;
66         int ret = -1;
67
68         n = test_decode_hex(hex, buf, sizeof buf);
69         if (n == -1) {
70                 fprintf(stderr, "%s: invalid hex sequence: %s\n",
71                                 progname, hex);
72                 goto out;
73         } else if (n > sizeof buf) {
74                 fprintf(stderr, "%s: hex sequence too long: %s\n",
75                                 progname, hex);
76                 goto out;
77         }
78
79         rc = upkg_decode_index(&index, buf, n);
80         if (rc == 0) {
81                 fprintf(stderr, "%s: invalid index encoding:\n", progname);
82                 print_bytes(stderr, 4, buf, n);
83                 goto out;
84         } else if (rc < n) {
85                 fprintf(stderr, "%s: trailing bytes in argument:\n", progname);
86                 print_bytes(stderr, 4, buf+rc, n-rc);
87                 /* Non-fatal */
88         }
89
90         ret = 0;
91 out:
92         printf("%ld\n", index);
93         return ret;
94 }
95
96 int main(int argc, char **argv)
97 {
98         int opt, ret = EXIT_SUCCESS;
99
100         if (argc > 0)
101                 progname = argv[0];
102
103         while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
104                 switch (opt) {
105                 case 'V':
106                         test_print_version(PROGNAME);
107                         return EXIT_SUCCESS;
108                 case 'H':
109                         print_help();
110                         return EXIT_SUCCESS;
111                 default:
112                         print_usage(stderr);
113                         return EXIT_FAILURE;
114                 }
115         }
116
117         if (!argv[optind]) {
118                 print_usage(stderr);
119                 return EXIT_FAILURE;
120         }
121
122         for (int i = optind; i < argc; i++) {
123                 if (print_index(argv[i]) != 0) {
124                         ret = EXIT_FAILURE;
125                 }
126         }
127
128         return ret;
129 }