Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libxo/xopo/xopo.c
39488 views
1
/*
2
* Copyright (c) 2014, 2015, Juniper Networks, Inc.
3
* All rights reserved.
4
* This SOFTWARE is licensed under the LICENSE provided in the
5
* ../Copyright file. By downloading, installing, copying, or otherwise
6
* using the SOFTWARE, you agree to be bound by the terms of that
7
* LICENSE.
8
* Phil Shafer, July 2015
9
*/
10
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <stdarg.h>
14
#include <unistd.h>
15
#include <string.h>
16
#include <ctype.h>
17
#include <sys/queue.h>
18
19
#include "xo_config.h"
20
#include "xo.h"
21
22
#include <getopt.h> /* Include after xo.h for testing */
23
24
#ifndef UNUSED
25
#define UNUSED __attribute__ ((__unused__))
26
#endif /* UNUSED */
27
28
static int opt_warn; /* Enable warnings */
29
static int opt_numbers; /* Number our fields */
30
31
typedef struct xopo_msg_s {
32
TAILQ_ENTRY(xopo_msg_s) xm_link;
33
char *xm_plural; /* If plural, points to the second part */
34
char xm_data[0]; /* Start of data */
35
} xopo_msg_t;
36
37
typedef TAILQ_HEAD(xopo_msg_list_s, xopo_msg_s) xopo_msg_list_t;
38
39
static xopo_msg_list_t field_list;
40
41
static void
42
xopo_msg_cb (const char *str, unsigned len, int plural)
43
{
44
int sz = sizeof(xopo_msg_t) + len + 1;
45
xopo_msg_t *xmp = malloc(sz);
46
if (xmp == NULL)
47
return;
48
49
bzero(xmp, sz);
50
memcpy(xmp->xm_data, str, len);
51
xmp->xm_data[len] = '\0';
52
53
if (plural) {
54
char *cp = strchr(xmp->xm_data, ',');
55
if (cp) {
56
*cp++ = '\0';
57
xmp->xm_plural = cp;
58
}
59
}
60
61
xopo_msg_t *xmp2;
62
63
TAILQ_FOREACH(xmp2, &field_list, xm_link) {
64
if (strcmp(xmp->xm_data, xmp2->xm_data) == 0) {
65
/* Houston, we have a negative on that trajectory */
66
free(xmp);
67
return;
68
}
69
}
70
71
TAILQ_INSERT_TAIL(&field_list, xmp, xm_link);
72
}
73
74
static void
75
print_version (void)
76
{
77
fprintf(stderr, "libxo version %s%s\n",
78
xo_version, xo_version_extra);
79
fprintf(stderr, "xopo version %s%s\n",
80
LIBXO_VERSION, LIBXO_VERSION_EXTRA);
81
}
82
83
static void
84
print_help (void)
85
{
86
fprintf(stderr,
87
"Usage: xopo [options] format [fields]\n"
88
" --help Display this help text\n"
89
" --option <opts> -or -O <opts> Give formatting options\n"
90
" --output <file> -or -o <file> Use file as output destination\n"
91
" --po <file> or -f <file> Generate new msgid's for a po file\n"
92
" --simplify <text> OR -s <text> Show simplified form of the format string\n"
93
" --version Display version information\n"
94
" --warn OR -W Display warnings in text on stderr\n"
95
);
96
}
97
98
static struct opts {
99
int o_help;
100
int o_version;
101
} opts;
102
103
static struct option long_opts[] = {
104
{ "help", no_argument, &opts.o_help, 1 },
105
{ "number", no_argument, NULL, 'n' },
106
{ "option", required_argument, NULL, 'O' },
107
{ "output", required_argument, NULL, 'o' },
108
{ "po", required_argument, NULL, 'f' },
109
{ "simplify", no_argument, NULL, 'S' },
110
{ "warn", no_argument, NULL, 'W' },
111
{ NULL, 0, NULL, 0 }
112
};
113
114
int
115
main (int argc UNUSED, char **argv)
116
{
117
char *opt_options = NULL;
118
char *opt_input = NULL;
119
char *opt_output = NULL;
120
char *opt_simplify = NULL;
121
int rc;
122
123
argc = xo_parse_args(argc, argv);
124
if (argc < 0)
125
return 1;
126
127
while ((rc = getopt_long(argc, argv, "f:no:O:s:W",
128
long_opts, NULL)) != -1) {
129
switch (rc) {
130
case 'f':
131
opt_input = optarg;
132
break;
133
134
case 'n':
135
opt_numbers = 1;
136
break;
137
138
case 'o':
139
opt_output = optarg;
140
break;
141
142
case 'O':
143
opt_options = optarg;
144
break;
145
146
case 's':
147
opt_simplify = optarg;
148
break;
149
150
case 'W':
151
opt_warn = 1;
152
xo_set_flags(NULL, XOF_WARN);
153
break;
154
155
case ':':
156
xo_errx(1, "missing argument");
157
break;
158
159
case 0:
160
if (opts.o_help) {
161
print_help();
162
return 1;
163
164
} else if (opts.o_version) {
165
print_version();
166
return 0;
167
168
} else {
169
print_help();
170
return 1;
171
}
172
173
bzero(&opts, sizeof(opts)); /* Reset all the options */
174
break;
175
176
default:
177
print_help();
178
return 1;
179
}
180
}
181
182
argc -= optind;
183
argv += optind;
184
185
if (opt_options) {
186
rc = xo_set_options(NULL, opt_options);
187
if (rc < 0)
188
xo_errx(1, "invalid options: %s", opt_options);
189
}
190
191
if (opt_simplify) {
192
char *fmt = xo_simplify_format(NULL, opt_simplify, opt_numbers, NULL);
193
if (fmt) {
194
xo_emit("{:format}\n", fmt);
195
free(fmt);
196
}
197
exit(0);
198
}
199
200
static char msgid[] = "msgid ";
201
char buf[BUFSIZ], *cp, *ep;
202
FILE *infile;
203
FILE *outfile;
204
TAILQ_INIT(&field_list);
205
206
if (opt_input) {
207
infile = fopen(opt_input, "r");
208
if (infile == NULL)
209
xo_emit_err(1, "count not open input file: '{:filename}'",
210
opt_input);
211
} else
212
infile = stdin;
213
214
if (opt_output) {
215
unlink(opt_output);
216
outfile = fopen(opt_output, "w");
217
if (outfile == NULL)
218
xo_emit_err(1, "count not open output file: '{:filename}'",
219
opt_output);
220
} else
221
outfile = stdout;
222
223
int blank = 0, line;
224
225
for (line = 1;; line++) {
226
if (fgets(buf, sizeof(buf), infile) == NULL)
227
break;
228
229
if (buf[0] == '#' && buf[1] == '\n')
230
continue;
231
232
blank = (buf[0] == '\n' && buf[1] == '\0');
233
234
if (strncmp(buf, msgid, sizeof(msgid) - 1) != 0) {
235
fprintf(outfile, "%s", buf);
236
continue;
237
}
238
239
for (cp = buf + sizeof(msgid); *cp; cp++)
240
if (!isspace((int) *cp))
241
break;
242
243
if (*cp == '"')
244
cp += 1;
245
246
ep = cp + strlen(cp);
247
if (ep > cp)
248
ep -= 1;
249
250
while (isspace((int) *ep) && ep > cp)
251
ep -= 1;
252
253
if (*ep != '"')
254
*ep += 1;
255
256
*ep = '\0';
257
258
cp = xo_simplify_format(NULL, cp, opt_numbers, xopo_msg_cb);
259
if (cp) {
260
fprintf(outfile, "msgid \"%s\"\n", cp);
261
free(cp);
262
}
263
}
264
265
if (!blank)
266
fprintf(outfile, "\n");
267
268
xopo_msg_t *xmp;
269
TAILQ_FOREACH(xmp, &field_list, xm_link) {
270
if (xmp->xm_plural) {
271
fprintf(outfile, "msgid \"%s\"\n"
272
"msgid_plural \"%s\"\n"
273
"msgstr[0] \"\"\n"
274
"msgstr[1] \"\"\n\n",
275
xmp->xm_data, xmp->xm_plural);
276
} else {
277
fprintf(outfile, "msgid \"%s\"\nmsgstr \"\"\n\n", xmp->xm_data);
278
}
279
}
280
281
if (infile != stdin)
282
fclose(infile);
283
if (outfile != stdout)
284
fclose(outfile);
285
286
xo_finish();
287
288
return 0;
289
}
290
291