aboutsummaryrefslogtreecommitdiff
path: root/contrib/libxo/xopo/xopo.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libxo/xopo/xopo.c')
-rw-r--r--contrib/libxo/xopo/xopo.c292
1 files changed, 292 insertions, 0 deletions
diff --git a/contrib/libxo/xopo/xopo.c b/contrib/libxo/xopo/xopo.c
new file mode 100644
index 000000000000..991b75795ed7
--- /dev/null
+++ b/contrib/libxo/xopo/xopo.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2014, 2015, Juniper Networks, Inc.
+ * All rights reserved.
+ * This SOFTWARE is licensed under the LICENSE provided in the
+ * ../Copyright file. By downloading, installing, copying, or otherwise
+ * using the SOFTWARE, you agree to be bound by the terms of that
+ * LICENSE.
+ * Phil Shafer, July 2015
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/queue.h>
+
+#include "xo_config.h"
+#include "xo.h"
+
+#include <getopt.h> /* Include after xo.h for testing */
+
+#ifndef UNUSED
+#define UNUSED __attribute__ ((__unused__))
+#endif /* UNUSED */
+
+static int opt_warn; /* Enable warnings */
+static int opt_numbers; /* Number our fields */
+
+typedef struct xopo_msg_s {
+ TAILQ_ENTRY(xopo_msg_s) xm_link;
+ char *xm_plural; /* If plural, points to the second part */
+ char xm_data[0]; /* Start of data */
+} xopo_msg_t;
+
+typedef TAILQ_HEAD(xopo_msg_list_s, xopo_msg_s) xopo_msg_list_t;
+
+static xopo_msg_list_t field_list;
+
+static void
+xopo_msg_cb (const char *str, unsigned len, int plural)
+{
+ int sz = sizeof(xopo_msg_t) + len + 1;
+ xopo_msg_t *xmp = malloc(sz);
+ if (xmp == NULL)
+ return;
+
+ bzero(xmp, sz);
+ memcpy(xmp->xm_data, str, len);
+ xmp->xm_data[len] = '\0';
+
+ if (plural) {
+ char *cp = strchr(xmp->xm_data, ',');
+ if (cp) {
+ *cp++ = '\0';
+ xmp->xm_plural = cp;
+ }
+ }
+
+ xopo_msg_t *xmp2;
+
+ TAILQ_FOREACH(xmp2, &field_list, xm_link) {
+ if (strcmp(xmp->xm_data, xmp2->xm_data) == 0) {
+ /* Houston, we have a negative on that trajectory */
+ free(xmp);
+ return;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(&field_list, xmp, xm_link);
+}
+
+static void
+print_version (void)
+{
+ fprintf(stderr, "libxo version %s%s\n",
+ xo_version, xo_version_extra);
+ fprintf(stderr, "xopo version %s%s\n",
+ LIBXO_VERSION, LIBXO_VERSION_EXTRA);
+}
+
+static void
+print_help (void)
+{
+ fprintf(stderr,
+"Usage: xopo [options] format [fields]\n"
+" --help Display this help text\n"
+" --option <opts> -or -O <opts> Give formatting options\n"
+" --output <file> -or -o <file> Use file as output destination\n"
+" --po <file> or -f <file> Generate new msgid's for a po file\n"
+" --simplify <text> OR -s <text> Show simplified form of the format string\n"
+" --version Display version information\n"
+" --warn OR -W Display warnings in text on stderr\n"
+);
+}
+
+static struct opts {
+ int o_help;
+ int o_version;
+} opts;
+
+static struct option long_opts[] = {
+ { "help", no_argument, &opts.o_help, 1 },
+ { "number", no_argument, NULL, 'n' },
+ { "option", required_argument, NULL, 'O' },
+ { "output", required_argument, NULL, 'o' },
+ { "po", required_argument, NULL, 'f' },
+ { "simplify", no_argument, NULL, 'S' },
+ { "warn", no_argument, NULL, 'W' },
+ { NULL, 0, NULL, 0 }
+};
+
+int
+main (int argc UNUSED, char **argv)
+{
+ char *fmt = NULL;
+ char *opt_options = NULL;
+ char *opt_input = NULL;
+ char *opt_output = NULL;
+ char *opt_simplify = NULL;
+ int rc;
+
+ argc = xo_parse_args(argc, argv);
+ if (argc < 0)
+ return 1;
+
+ while ((rc = getopt_long(argc, argv, "f:no:O:s:W",
+ long_opts, NULL)) != -1) {
+ switch (rc) {
+ case 'f':
+ opt_input = optarg;
+ break;
+
+ case 'n':
+ opt_numbers = 1;
+ break;
+
+ case 'o':
+ opt_output = optarg;
+ break;
+
+ case 'O':
+ opt_options = optarg;
+ break;
+
+ case 's':
+ opt_simplify = optarg;
+ break;
+
+ case 'W':
+ opt_warn = 1;
+ xo_set_flags(NULL, XOF_WARN);
+ break;
+
+ case ':':
+ xo_errx(1, "missing argument");
+ break;
+
+ case 0:
+ if (opts.o_help) {
+ print_help();
+ return 1;
+
+ } else if (opts.o_version) {
+ print_version();
+ return 0;
+
+ } else {
+ print_help();
+ return 1;
+ }
+
+ bzero(&opts, sizeof(opts)); /* Reset all the options */
+ break;
+
+ default:
+ print_help();
+ return 1;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (opt_options) {
+ rc = xo_set_options(NULL, opt_options);
+ if (rc < 0)
+ xo_errx(1, "invalid options: %s", opt_options);
+ }
+
+ fmt = *argv++;
+
+ if (opt_simplify) {
+ fmt = xo_simplify_format(NULL, opt_simplify, opt_numbers, NULL);
+ if (fmt) {
+ xo_emit("{:format}\n", fmt);
+ free(fmt);
+ }
+ exit(0);
+ }
+
+ static char msgid[] = "msgid ";
+ char buf[BUFSIZ], *cp, *ep;
+ FILE *infile;
+ FILE *outfile;
+ TAILQ_INIT(&field_list);
+
+ if (opt_input) {
+ infile = fopen(opt_input, "r");
+ if (infile == NULL)
+ xo_emit_err(1, "count not open input file: '{:filename}'",
+ opt_input);
+ } else
+ infile = stdin;
+
+ if (opt_output) {
+ unlink(opt_output);
+ outfile = fopen(opt_output, "w");
+ if (outfile == NULL)
+ xo_emit_err(1, "count not open output file: '{:filename}'",
+ opt_output);
+ } else
+ outfile = stdout;
+
+ int blank = 0, line;
+
+ for (line = 1;; line++) {
+ if (fgets(buf, sizeof(buf), infile) == NULL)
+ break;
+
+ if (buf[0] == '#' && buf[1] == '\n')
+ continue;
+
+ blank = (buf[0] == '\n' && buf[1] == '\0');
+
+ if (strncmp(buf, msgid, sizeof(msgid) - 1) != 0) {
+ fprintf(outfile, "%s", buf);
+ continue;
+ }
+
+ for (cp = buf + sizeof(msgid); *cp; cp++)
+ if (!isspace((int) *cp))
+ break;
+
+ if (*cp == '"')
+ cp += 1;
+
+ ep = cp + strlen(cp);
+ if (ep > cp)
+ ep -= 1;
+
+ while (isspace((int) *ep) && ep > cp)
+ ep -= 1;
+
+ if (*ep != '"')
+ *ep += 1;
+
+ *ep = '\0';
+
+ cp = xo_simplify_format(NULL, cp, opt_numbers, xopo_msg_cb);
+ if (cp) {
+ fprintf(outfile, "msgid \"%s\"\n", cp);
+ free(cp);
+ }
+ }
+
+ if (!blank)
+ fprintf(outfile, "\n");
+
+ xopo_msg_t *xmp;
+ TAILQ_FOREACH(xmp, &field_list, xm_link) {
+ if (xmp->xm_plural) {
+ fprintf(outfile, "msgid \"%s\"\n"
+ "msgid_plural \"%s\"\n"
+ "msgstr[0] \"\"\n"
+ "msgstr[1] \"\"\n\n",
+ xmp->xm_data, xmp->xm_plural);
+ } else {
+ fprintf(outfile, "msgid \"%s\"\nmsgstr \"\"\n\n", xmp->xm_data);
+ }
+ }
+
+ if (infile != stdin)
+ fclose(infile);
+ if (outfile != stdout)
+ fclose(outfile);
+
+ xo_finish();
+
+ return 0;
+}