tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: [PATCH 1/2] Add BSD-licensed gettext(1) implementation
In article <1433139701-11940-2-git-send-email-will%worrbase.com@localhost>,
William Orr <will%worrbase.com@localhost> wrote:
>Simple gettext implementation that models GNU gettext(1). Is
>feature-complete compared to GNU gettext(1).
>
>Needs manpages and tests
>---
> src/usr.bin/gettext/Makefile | 12 +++
> src/usr.bin/gettext/gettext.c | 237 ++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 249 insertions(+)
> create mode 100644 src/usr.bin/gettext/Makefile
> create mode 100644 src/usr.bin/gettext/gettext.c
>
>diff --git a/src/usr.bin/gettext/Makefile b/src/usr.bin/gettext/Makefile
>new file mode 100644
>index 0000000..b928780
>--- /dev/null
>+++ b/src/usr.bin/gettext/Makefile
>@@ -0,0 +1,12 @@
>+.include <bsd.own.mk>
>+
>+PROG= gettext
>+SRCS= gettext.c
>+
>+CFLAGS+=-g
Delete -g
>+
>+LDADD+= -lintl
DPADD+= ${LIBINTL}
>+
>+MAN= gettext.1
>+
>+.include <bsd.prog.mk>
>+extern char *optarg;
>+extern int optopt;
>+extern int optind;
delete, provided.
>+
>+static bool nflag;
>+
>+static void
>+usage(char *progname, int exit_status)
>+{
>+
>+ printf("Usage: %s [-ehn] [[TEXTDOMAIN] MSGID]\n", basename(progname));
>+ printf("Usage: %s -s [MSGID]...\n", basename(progname));
getprogname();
>+ exit(exit_status);
>+}
>+
>+static void
>+expand(char *str)
>+{
>+ char *fp, *sp, ch, pl;
>+
>+ for (fp = str, sp = str; *fp != 0;) {
>+ if (*fp == '\\') {
>+ switch (*++fp) {
>+ case 'a':
>+ *sp++ = '\a';
>+ fp++;
>+ break;
>+ case 'b':
>+ *sp++ = '\b';
>+ fp++;
>+ break;
>+ case 'c':
>+ nflag = true;
>+ fp++;
>+ break;
>+ case 'f':
>+ *sp++ = '\f';
>+ fp++;
>+ break;
>+ case 'n':
>+ *sp++ = '\n';
>+ fp++;
>+ break;
>+ case 'r':
>+ *sp++ = '\r';
>+ fp++;
>+ break;
>+ case 't':
>+ *sp++ = '\t';
>+ fp++;
>+ break;
>+ case 'v':
>+ *sp++ = '\v';
>+ fp++;
>+ break;
>+ case '\\':
>+ *sp++ = '\\';
>+ fp++;
>+ break;
>+ case '0':
>+ case '1':
>+ case '2':
>+ case '3':
>+ case '4':
>+ case '5':
>+ case '6':
>+ case '7':
>+ ch = *fp++ - '0';
>+ pl = 0;
>+ while (*fp >= '0' && *fp <= '7' && pl < 2) {
>+ ch *= 8;
>+ ch += *fp++ - '0';
>+ pl++;
>+ }
>+
>+ *sp++ = ch;
>+ break;
>+ default:
>+ *sp++ = '\\';
>+ break;
>+ }
>+ }
>+ *sp++ = *fp++;
>+ }
>+
>+ *sp = '\0';
>+}
>+
>+static char *
>+gettext_getenv(const char *env, size_t len)
>+{
>+ char *ret = NULL;
>+
>+ ret = calloc(len, 1);
>+ if (ret == NULL)
>+ err(EXIT_FAILURE, "can't allocate memory");
>+
>+ if (getenv_r(env, ret, len)) {
>+ free(ret);
>+ ret = NULL;
>+
>+ if (errno != ENOENT)
>+ err(EXIT_FAILURE, "couldn't read %s from env", env);
>+ }
>+ return ret;
Why this complexity? It is not re-entrant/threaded just use regular
getenv, estrdup() it.
>+}
>+
>+int
>+main(int argc, char **argv)
>+{
>+ char *msgdomain = NULL;
>+ char *msgdomaindir = NULL;
>+ char *msgid = NULL;
>+ char *progname = NULL;
>+ char *translation = NULL;
>+ bool eflag = false;
>+ bool sflag = false;
>+ int ch;
>+
>+ setlocale(LC_ALL, "");
also setprogname();
>+
>+ while ((ch = getopt(argc, argv, "d:eEhnsV")) != -1) {
>+ switch (ch) {
>+ case 'd':
>+ msgdomain = strdup(optarg);
>+ if (msgdomain == NULL)
>+ err(EXIT_FAILURE, "can't allocate memory");
estrdup()?
>+ break;
>+ case 'e':
>+ eflag = true;
>+ break;
>+ case 'h':
>+ usage(argv[0], EXIT_SUCCESS);
>+ /* NOTREACHED */
>+ break;
>+ case 'n':
>+ nflag = true;
>+ break;
>+ case 's':
>+ sflag = true;
>+ break;
>+ case 'E':
>+ /* GNU gettext compat */
>+ break;
Sort options.
>+ default:
>+ usage(argv[0], EXIT_FAILURE);
>+ /* NOTREACHED */
>+ break;
>+ }
>+ }
>+ progname = argv[0];
>+ argc -= optind;
>+ argv += optind;
>+
>+ if (argc == 0) {
>+ fprintf(stderr, "missing msgid\n");
warnx()?
>+ usage(progname, EXIT_FAILURE);
>+ }
>+ /* msgdomain can be passed as optional arg iff -s is not passed */
>+ if (argc == 2 && !sflag) {
>+ msgdomain = strdup(argv[0]);
>+ if (msgdomain == NULL)
>+ err(EXIT_FAILURE, "can't allocate memory");
estrdup()?
>+
>+ argc -= 1;
>+ argv += 1;
>+ } else if (argc > 2 && !sflag) {
>+ fprintf(stderr, "%s: too many arguments\n", basename(progname));
warnx()?
>+ usage(progname, EXIT_FAILURE);
>+ }
>+ /* msgdomain can be passed as env var */
>+ if (msgdomain == NULL)
>+ msgdomain = gettext_getenv("TEXTDOMAIN", PATH_MAX);
>+
>+ if (msgdomain != NULL) {
>+ msgdomaindir = gettext_getenv("TEXTDOMAINDIR", PATH_MAX);
>+ if (msgdomaindir)
>+ bindtextdomain(msgdomain, msgdomaindir);
>+ }
>+ do {
>+ if (eflag)
>+ expand(*argv);
>+
>+ translation = dgettext(msgdomain, argv[0]);
>+ printf("%s", translation);
>+
>+ argc--;
>+ argv++;
>+ if (argc)
>+ printf(" ");
>+ } while (sflag && argc != 0);
>+
>+ if (sflag && !nflag)
>+ printf("\n");
>+
>+ free(msgdomain);
>+ free(msgdomaindir);
>+ return EXIT_SUCCESS;
>+}
Home |
Main Index |
Thread Index |
Old Index