1 /* $NetBSD: gettext.c,v 1.2 2015/06/03 23:15:22 enami Exp $ */ 2 3 /*- 4 * Copyright (c) 2015 William Orr <will@worrbase.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: gettext.c,v 1.2 2015/06/03 23:15:22 enami Exp $"); 30 31 #include <err.h> 32 #include <errno.h> 33 #include <getopt.h> 34 #include <libintl.h> 35 #include <locale.h> 36 #include <stdbool.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <util.h> 41 42 static __dead void 43 usage(int exit_status) 44 { 45 46 fprintf(stderr, "Usage: %s [-ehn] [[<textdomain>] <msgid>]\n", 47 getprogname()); 48 fprintf(stderr, "Usage: %s -s [<msgid>]...\n", getprogname()); 49 exit(exit_status); 50 } 51 52 static bool 53 expand(char *str) 54 { 55 char *fp, *sp, ch, pl; 56 bool nflag = false; 57 58 for (fp = str, sp = str; *fp != 0;) { 59 if (*fp == '\\') { 60 switch (*++fp) { 61 case 'a': 62 *sp++ = '\a'; 63 fp++; 64 break; 65 case 'b': 66 *sp++ = '\b'; 67 fp++; 68 break; 69 case 'c': 70 nflag = true; 71 fp++; 72 break; 73 case 'f': 74 *sp++ = '\f'; 75 fp++; 76 break; 77 case 'n': 78 *sp++ = '\n'; 79 fp++; 80 break; 81 case 'r': 82 *sp++ = '\r'; 83 fp++; 84 break; 85 case 't': 86 *sp++ = '\t'; 87 fp++; 88 break; 89 case 'v': 90 *sp++ = '\v'; 91 fp++; 92 break; 93 case '\\': 94 *sp++ = '\\'; 95 fp++; 96 break; 97 case '0': 98 case '1': 99 case '2': 100 case '3': 101 case '4': 102 case '5': 103 case '6': 104 case '7': 105 ch = *fp++ - '0'; 106 pl = 0; 107 while (*fp >= '0' && *fp <= '7' && pl < 2) { 108 ch *= 8; 109 ch += *fp++ - '0'; 110 pl++; 111 } 112 113 *sp++ = ch; 114 break; 115 default: 116 *sp++ = '\\'; 117 break; 118 } 119 continue; 120 } 121 *sp++ = *fp++; 122 } 123 124 *sp = '\0'; 125 return nflag; 126 } 127 128 int 129 main(int argc, char **argv) 130 { 131 char *msgdomain = NULL; 132 char *msgdomaindir = NULL; 133 char *translation = NULL; 134 char *s; 135 bool eflag = false; 136 bool sflag = false; 137 bool nflag = false; 138 int ch; 139 140 setlocale(LC_ALL, ""); 141 setprogname(argv[0]); 142 143 while ((ch = getopt(argc, argv, "d:EehnsV")) != -1) { 144 switch (ch) { 145 case 'd': 146 msgdomain = estrdup(optarg); 147 break; 148 case 'E': 149 /* GNU gettext compat */ 150 break; 151 case 'e': 152 eflag = true; 153 break; 154 case 'V': 155 case 'h': 156 free(msgdomain); 157 usage(EXIT_SUCCESS); 158 /* NOTREACHED */ 159 case 'n': 160 nflag = true; 161 break; 162 case 's': 163 sflag = true; 164 break; 165 default: 166 free(msgdomain); 167 usage(EXIT_FAILURE); 168 /* NOTREACHED */ 169 } 170 } 171 argc -= optind; 172 argv += optind; 173 174 if (argc == 0) { 175 free(msgdomain); 176 errx(EXIT_FAILURE, "missing msgid"); 177 } 178 179 /* msgdomain can be passed as optional arg iff -s is not passed */ 180 if (!sflag) { 181 if (argc == 2) { 182 free(msgdomain); 183 msgdomain = estrdup(argv[0]); 184 185 argc -= 1; 186 argv += 1; 187 } else if (argc > 2) 188 errx(EXIT_FAILURE, "too many arguments"); 189 } 190 191 /* msgdomain can be passed as env var */ 192 if (msgdomain == NULL) { 193 if ((s = getenv("TEXTDOMAIN")) != NULL) 194 msgdomain = estrdup(s); 195 } 196 197 if (msgdomain != NULL) { 198 if ((s = getenv("TEXTDOMAINDIR")) != NULL) 199 msgdomaindir = estrdup(s); 200 if (msgdomaindir) 201 bindtextdomain(msgdomain, msgdomaindir); 202 } 203 204 do { 205 if (eflag) 206 nflag |= expand(*argv); 207 208 translation = dgettext(msgdomain, argv[0]); 209 printf("%s", translation); 210 211 argc--; 212 argv++; 213 if (argc) 214 printf(" "); 215 } while (sflag && argc != 0); 216 217 if (sflag && !nflag) 218 printf("\n"); 219 220 free(msgdomain); 221 free(msgdomaindir); 222 223 return EXIT_SUCCESS; 224 } 225