1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include "sun_msgfmt.h" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate static void read_psffm(char *); 32*7c478bd9Sstevel@tonic-gate static void sortit(char *, char *); 33*7c478bd9Sstevel@tonic-gate static wchar_t *consume_whitespace(wchar_t *); 34*7c478bd9Sstevel@tonic-gate static char expand_meta(wchar_t **); 35*7c478bd9Sstevel@tonic-gate static struct domain_struct *find_domain_node(char *); 36*7c478bd9Sstevel@tonic-gate static void insert_message(struct domain_struct *, char *, char *); 37*7c478bd9Sstevel@tonic-gate static void output_all_mo_files(void); 38*7c478bd9Sstevel@tonic-gate static void output_one_mo_file(struct domain_struct *); 39*7c478bd9Sstevel@tonic-gate static size_t _mbsntowcs(wchar_t **, char **, size_t *); 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 42*7c478bd9Sstevel@tonic-gate static void printlist(void); 43*7c478bd9Sstevel@tonic-gate #endif 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate static char gcurrent_domain[TEXTDOMAINMAX+1]; 46*7c478bd9Sstevel@tonic-gate static char *gmsgid; /* Stores msgid when read po file */ 47*7c478bd9Sstevel@tonic-gate static char *gmsgstr; /* Stores msgstr when read po file */ 48*7c478bd9Sstevel@tonic-gate static int gmsgid_size; /* The current size of msgid buffer */ 49*7c478bd9Sstevel@tonic-gate static int gmsgstr_size; /* The current size of msgstr buffer */ 50*7c478bd9Sstevel@tonic-gate static char *outfile = NULL; 51*7c478bd9Sstevel@tonic-gate static int linenum; /* The line number in the file */ 52*7c478bd9Sstevel@tonic-gate static int msgid_linenum; /* The last msgid token line number */ 53*7c478bd9Sstevel@tonic-gate static int msgstr_linenum; /* The last msgstr token line number */ 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate static int oflag = 0; 56*7c478bd9Sstevel@tonic-gate static int sun_p = 0; 57*7c478bd9Sstevel@tonic-gate int verbose = 0; 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate static struct domain_struct *first_domain = NULL; 60*7c478bd9Sstevel@tonic-gate static struct domain_struct *last_used_domain = NULL; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate static int mbcurmax; 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate static char **oargv; 65*7c478bd9Sstevel@tonic-gate static char *inputdir; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate extern void check_gnu(char *, size_t); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate #define GNU_MSGFMT "/usr/lib/gmsgfmt" 70*7c478bd9Sstevel@tonic-gate void 71*7c478bd9Sstevel@tonic-gate invoke_gnu_msgfmt(void) 72*7c478bd9Sstevel@tonic-gate { 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Transferring to /usr/lib/gmsgfmt 75*7c478bd9Sstevel@tonic-gate */ 76*7c478bd9Sstevel@tonic-gate char *gnu_msgfmt; 77*7c478bd9Sstevel@tonic-gate #ifdef DEBUG_MSGFMT 78*7c478bd9Sstevel@tonic-gate gnu_msgfmt = getenv("GNU_MSGFMT"); 79*7c478bd9Sstevel@tonic-gate if (!gnu_msgfmt) 80*7c478bd9Sstevel@tonic-gate gnu_msgfmt = GNU_MSGFMT; 81*7c478bd9Sstevel@tonic-gate #else 82*7c478bd9Sstevel@tonic-gate gnu_msgfmt = GNU_MSGFMT; 83*7c478bd9Sstevel@tonic-gate #endif 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate if (verbose) { 86*7c478bd9Sstevel@tonic-gate diag(gettext(DIAG_INVOKING_GNU)); 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate (void) execv(gnu_msgfmt, oargv); 90*7c478bd9Sstevel@tonic-gate /* exec failed */ 91*7c478bd9Sstevel@tonic-gate error(gettext(ERR_EXEC_FAILED), gnu_msgfmt); 92*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate static void 96*7c478bd9Sstevel@tonic-gate usage(void) 97*7c478bd9Sstevel@tonic-gate { 98*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext(ERR_USAGE)); 99*7c478bd9Sstevel@tonic-gate exit(2); 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * msgfmt - Generate binary tree for runtime gettext() using psffm: "Portable 104*7c478bd9Sstevel@tonic-gate * Source File Format for Messages" file template. This file may have 105*7c478bd9Sstevel@tonic-gate * previously been generated by the xgettext filter for c source files. 106*7c478bd9Sstevel@tonic-gate */ 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate int 109*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 110*7c478bd9Sstevel@tonic-gate { 111*7c478bd9Sstevel@tonic-gate int ret; 112*7c478bd9Sstevel@tonic-gate static struct flags flag; 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 115*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 116*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 117*7c478bd9Sstevel@tonic-gate #endif 118*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate oargv = argv; 121*7c478bd9Sstevel@tonic-gate ret = parse_option(&argc, &argv, &flag); 122*7c478bd9Sstevel@tonic-gate if (ret == -1) { 123*7c478bd9Sstevel@tonic-gate usage(); 124*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate if (flag.sun_p) { 128*7c478bd9Sstevel@tonic-gate /* never invoke gnu msgfmt */ 129*7c478bd9Sstevel@tonic-gate if (flag.gnu_p) { 130*7c478bd9Sstevel@tonic-gate error(gettext(ERR_GNU_ON_SUN)); 131*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate sun_p = flag.sun_p; 134*7c478bd9Sstevel@tonic-gate } 135*7c478bd9Sstevel@tonic-gate if (flag.idir) { 136*7c478bd9Sstevel@tonic-gate inputdir = flag.idir; 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate if (flag.ofile) { 139*7c478bd9Sstevel@tonic-gate oflag = 1; 140*7c478bd9Sstevel@tonic-gate outfile = flag.ofile; 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate if (flag.verbose) { 143*7c478bd9Sstevel@tonic-gate verbose = 1; 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate 146*7c478bd9Sstevel@tonic-gate if (flag.gnu_p) { 147*7c478bd9Sstevel@tonic-gate /* invoke /usr/lib/gmsgfmt */ 148*7c478bd9Sstevel@tonic-gate invoke_gnu_msgfmt(); 149*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* 153*7c478bd9Sstevel@tonic-gate * read all portable object files specified in command arguments. 154*7c478bd9Sstevel@tonic-gate * Allocate initial size for msgid and msgstr. If it needs more 155*7c478bd9Sstevel@tonic-gate * spaces, realloc later. 156*7c478bd9Sstevel@tonic-gate */ 157*7c478bd9Sstevel@tonic-gate gmsgid = (char *)Xmalloc(MAX_VALUE_LEN); 158*7c478bd9Sstevel@tonic-gate gmsgstr = (char *)Xmalloc(MAX_VALUE_LEN); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate gmsgid_size = gmsgstr_size = MAX_VALUE_LEN; 161*7c478bd9Sstevel@tonic-gate (void) memset(gmsgid, 0, gmsgid_size); 162*7c478bd9Sstevel@tonic-gate (void) memset(gmsgstr, 0, gmsgstr_size); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate mbcurmax = MB_CUR_MAX; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate while (argc-- > 0) { 167*7c478bd9Sstevel@tonic-gate if (verbose) { 168*7c478bd9Sstevel@tonic-gate diag(gettext(DIAG_START_PROC), *argv); 169*7c478bd9Sstevel@tonic-gate } 170*7c478bd9Sstevel@tonic-gate read_psffm(*argv++); 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate output_all_mo_files(); 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 176*7c478bd9Sstevel@tonic-gate printlist(); 177*7c478bd9Sstevel@tonic-gate #endif 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate return (0); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate } /* main */ 182*7c478bd9Sstevel@tonic-gate 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * read_psffm - read in "psffm" format file, check syntax, printing error 187*7c478bd9Sstevel@tonic-gate * messages as needed, output binary tree to file <domain> 188*7c478bd9Sstevel@tonic-gate */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate static void 191*7c478bd9Sstevel@tonic-gate read_psffm(char *file) 192*7c478bd9Sstevel@tonic-gate { 193*7c478bd9Sstevel@tonic-gate int fd; 194*7c478bd9Sstevel@tonic-gate static char msgfile[MAXPATHLEN]; 195*7c478bd9Sstevel@tonic-gate wchar_t *linebufptr, *p; 196*7c478bd9Sstevel@tonic-gate char *bufptr = 0; 197*7c478bd9Sstevel@tonic-gate int quotefound; /* double quote was seen */ 198*7c478bd9Sstevel@tonic-gate int inmsgid = 0; /* indicates "msgid" was seen */ 199*7c478bd9Sstevel@tonic-gate int inmsgstr = 0; /* indicates "msgstr" was seen */ 200*7c478bd9Sstevel@tonic-gate int indomain = 0; /* indicates "domain" was seen */ 201*7c478bd9Sstevel@tonic-gate wchar_t wc; 202*7c478bd9Sstevel@tonic-gate char mb; 203*7c478bd9Sstevel@tonic-gate int n; 204*7c478bd9Sstevel@tonic-gate char token_found; /* Boolean value */ 205*7c478bd9Sstevel@tonic-gate unsigned int bufptr_index = 0; /* current index of bufptr */ 206*7c478bd9Sstevel@tonic-gate char *mbuf, *addr; 207*7c478bd9Sstevel@tonic-gate size_t fsize, ln_size, ll; 208*7c478bd9Sstevel@tonic-gate wchar_t *linebufhead = NULL; 209*7c478bd9Sstevel@tonic-gate struct stat64 statbuf; 210*7c478bd9Sstevel@tonic-gate char *filename; 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * For each po file to be read, 214*7c478bd9Sstevel@tonic-gate * 1) set domain to default and 215*7c478bd9Sstevel@tonic-gate * 2) set linenumer to 0. 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate (void) strcpy(gcurrent_domain, DEFAULT_DOMAIN); 218*7c478bd9Sstevel@tonic-gate linenum = 0; 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if (!inputdir) { 221*7c478bd9Sstevel@tonic-gate filename = Xstrdup(file); 222*7c478bd9Sstevel@tonic-gate } else { 223*7c478bd9Sstevel@tonic-gate size_t dirlen, filelen, len; 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate dirlen = strlen(inputdir); 226*7c478bd9Sstevel@tonic-gate filelen = strlen(file); 227*7c478bd9Sstevel@tonic-gate len = dirlen + 1 + filelen + 1; 228*7c478bd9Sstevel@tonic-gate filename = (char *)Xmalloc(len); 229*7c478bd9Sstevel@tonic-gate (void) memcpy(filename, inputdir, dirlen); 230*7c478bd9Sstevel@tonic-gate *(filename + dirlen) = '/'; 231*7c478bd9Sstevel@tonic-gate (void) memcpy(filename + dirlen + 1, file, filelen); 232*7c478bd9Sstevel@tonic-gate *(filename + dirlen + 1 + filelen) = '\0'; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate fd = open(filename, O_RDONLY); 236*7c478bd9Sstevel@tonic-gate if (fd == -1) { 237*7c478bd9Sstevel@tonic-gate error(gettext(ERR_OPEN_FAILED), filename); 238*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate if (fstat64(fd, &statbuf) == -1) { 241*7c478bd9Sstevel@tonic-gate error(gettext(ERR_STAT_FAILED), filename); 242*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate fsize = (size_t)statbuf.st_size; 245*7c478bd9Sstevel@tonic-gate if (fsize == 0) { 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * The size of the specified po file is 0. 248*7c478bd9Sstevel@tonic-gate * In Solaris 8 and earlier, msgfmt was silent 249*7c478bd9Sstevel@tonic-gate * for the null po file. So, just returns 250*7c478bd9Sstevel@tonic-gate * without generating an error message. 251*7c478bd9Sstevel@tonic-gate */ 252*7c478bd9Sstevel@tonic-gate (void) close(fd); 253*7c478bd9Sstevel@tonic-gate free(filename); 254*7c478bd9Sstevel@tonic-gate return; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate addr = mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0); 257*7c478bd9Sstevel@tonic-gate if (addr == MAP_FAILED) { 258*7c478bd9Sstevel@tonic-gate error(gettext(ERR_MMAP_FAILED), filename); 259*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate (void) close(fd); 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate if (!sun_p) 264*7c478bd9Sstevel@tonic-gate check_gnu(addr, fsize); 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate mbuf = addr; 267*7c478bd9Sstevel@tonic-gate for (;;) { 268*7c478bd9Sstevel@tonic-gate if (linebufhead) { 269*7c478bd9Sstevel@tonic-gate free(linebufhead); 270*7c478bd9Sstevel@tonic-gate linebufhead = NULL; 271*7c478bd9Sstevel@tonic-gate } 272*7c478bd9Sstevel@tonic-gate ln_size = _mbsntowcs(&linebufhead, &mbuf, &fsize); 273*7c478bd9Sstevel@tonic-gate if (ln_size == (size_t)-1) { 274*7c478bd9Sstevel@tonic-gate error(gettext(ERR_READ_FAILED), filename); 275*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 276*7c478bd9Sstevel@tonic-gate } else if (ln_size == 0) { 277*7c478bd9Sstevel@tonic-gate break; /* End of File. */ 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate linenum++; 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate linebufptr = linebufhead; 282*7c478bd9Sstevel@tonic-gate quotefound = 0; 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate switch (*linebufptr) { 285*7c478bd9Sstevel@tonic-gate case L'#': /* comment */ 286*7c478bd9Sstevel@tonic-gate case L'\n': /* empty line */ 287*7c478bd9Sstevel@tonic-gate continue; 288*7c478bd9Sstevel@tonic-gate case L'\"': /* multiple lines of msgid and msgstr */ 289*7c478bd9Sstevel@tonic-gate quotefound = 1; 290*7c478bd9Sstevel@tonic-gate break; 291*7c478bd9Sstevel@tonic-gate } 292*7c478bd9Sstevel@tonic-gate 293*7c478bd9Sstevel@tonic-gate /* 294*7c478bd9Sstevel@tonic-gate * Process MSGID Tokens. 295*7c478bd9Sstevel@tonic-gate */ 296*7c478bd9Sstevel@tonic-gate token_found = (wcsncmp(MSGID_TOKEN, linebufptr, 297*7c478bd9Sstevel@tonic-gate MSGID_LEN) == 0) ? 1 : 0; 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate if (token_found || (quotefound && inmsgid)) { 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (token_found) { 302*7c478bd9Sstevel@tonic-gate if (!CK_NXT_CH(linebufptr, MSGID_LEN+1)) { 303*7c478bd9Sstevel@tonic-gate diag(gettext(ERR_NOSPC), linenum); 304*7c478bd9Sstevel@tonic-gate error(gettext(ERR_EXITING)); 305*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate if (inmsgid && !quotefound) { 310*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_NO_MSGSTR), msgid_linenum); 311*7c478bd9Sstevel@tonic-gate continue; 312*7c478bd9Sstevel@tonic-gate } 313*7c478bd9Sstevel@tonic-gate if (inmsgstr) { 314*7c478bd9Sstevel@tonic-gate sortit(gmsgid, gmsgstr); 315*7c478bd9Sstevel@tonic-gate (void) memset(gmsgid, 0, gmsgid_size); 316*7c478bd9Sstevel@tonic-gate (void) memset(gmsgstr, 0, gmsgstr_size); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate 319*7c478bd9Sstevel@tonic-gate if (inmsgid) { 320*7c478bd9Sstevel@tonic-gate /* multiple lines of msgid */ 321*7c478bd9Sstevel@tonic-gate /* cancel the previous null termination */ 322*7c478bd9Sstevel@tonic-gate bufptr_index--; 323*7c478bd9Sstevel@tonic-gate } else { 324*7c478bd9Sstevel@tonic-gate /* 325*7c478bd9Sstevel@tonic-gate * The first line of msgid. 326*7c478bd9Sstevel@tonic-gate * Save linenum of msgid to be used when 327*7c478bd9Sstevel@tonic-gate * printing warning or error message. 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate msgid_linenum = linenum; 330*7c478bd9Sstevel@tonic-gate p = linebufptr; 331*7c478bd9Sstevel@tonic-gate linebufptr = consume_whitespace( 332*7c478bd9Sstevel@tonic-gate linebufptr + MSGID_LEN); 333*7c478bd9Sstevel@tonic-gate ln_size -= linebufptr - p; 334*7c478bd9Sstevel@tonic-gate bufptr = gmsgid; 335*7c478bd9Sstevel@tonic-gate bufptr_index = 0; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate inmsgid = 1; 339*7c478bd9Sstevel@tonic-gate inmsgstr = 0; 340*7c478bd9Sstevel@tonic-gate indomain = 0; 341*7c478bd9Sstevel@tonic-gate goto load_buffer; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Process MSGSTR Tokens. 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate token_found = (wcsncmp(MSGSTR_TOKEN, linebufptr, 348*7c478bd9Sstevel@tonic-gate MSGSTR_LEN) == 0) ? 1 : 0; 349*7c478bd9Sstevel@tonic-gate if (token_found || (quotefound && inmsgstr)) { 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate if (token_found) { 352*7c478bd9Sstevel@tonic-gate if (!CK_NXT_CH(linebufptr, MSGSTR_LEN+1)) { 353*7c478bd9Sstevel@tonic-gate diag(gettext(ERR_NOSPC), linenum); 354*7c478bd9Sstevel@tonic-gate error(gettext(ERR_EXITING)); 355*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 356*7c478bd9Sstevel@tonic-gate } 357*7c478bd9Sstevel@tonic-gate } 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate if (inmsgstr && !quotefound) { 361*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_NO_MSGID), msgstr_linenum); 362*7c478bd9Sstevel@tonic-gate continue; 363*7c478bd9Sstevel@tonic-gate } 364*7c478bd9Sstevel@tonic-gate if (inmsgstr) { 365*7c478bd9Sstevel@tonic-gate /* multiple lines of msgstr */ 366*7c478bd9Sstevel@tonic-gate /* cancel the previous null termination */ 367*7c478bd9Sstevel@tonic-gate bufptr_index--; 368*7c478bd9Sstevel@tonic-gate } else { 369*7c478bd9Sstevel@tonic-gate /* 370*7c478bd9Sstevel@tonic-gate * The first line of msgstr. 371*7c478bd9Sstevel@tonic-gate * Save linenum of msgid to be used when 372*7c478bd9Sstevel@tonic-gate * printing warning or error message. 373*7c478bd9Sstevel@tonic-gate */ 374*7c478bd9Sstevel@tonic-gate msgstr_linenum = linenum; 375*7c478bd9Sstevel@tonic-gate p = linebufptr; 376*7c478bd9Sstevel@tonic-gate linebufptr = consume_whitespace( 377*7c478bd9Sstevel@tonic-gate linebufptr + MSGSTR_LEN); 378*7c478bd9Sstevel@tonic-gate ln_size -= linebufptr - p; 379*7c478bd9Sstevel@tonic-gate bufptr = gmsgstr; 380*7c478bd9Sstevel@tonic-gate bufptr_index = 0; 381*7c478bd9Sstevel@tonic-gate } 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate inmsgstr = 1; 384*7c478bd9Sstevel@tonic-gate inmsgid = 0; 385*7c478bd9Sstevel@tonic-gate indomain = 0; 386*7c478bd9Sstevel@tonic-gate goto load_buffer; 387*7c478bd9Sstevel@tonic-gate } 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate /* 390*7c478bd9Sstevel@tonic-gate * Process DOMAIN Tokens. 391*7c478bd9Sstevel@tonic-gate * Add message id and message string to sorted list 392*7c478bd9Sstevel@tonic-gate * if msgstr was processed last time. 393*7c478bd9Sstevel@tonic-gate */ 394*7c478bd9Sstevel@tonic-gate token_found = (wcsncmp(DOMAIN_TOKEN, linebufptr, 395*7c478bd9Sstevel@tonic-gate DOMAIN_LEN) == 0) ? 1 : 0; 396*7c478bd9Sstevel@tonic-gate if ((token_found) || (quotefound && indomain)) { 397*7c478bd9Sstevel@tonic-gate if (token_found) { 398*7c478bd9Sstevel@tonic-gate if (!CK_NXT_CH(linebufptr, DOMAIN_LEN+1)) { 399*7c478bd9Sstevel@tonic-gate diag(gettext(ERR_NOSPC), linenum); 400*7c478bd9Sstevel@tonic-gate error(gettext(ERR_EXITING)); 401*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 402*7c478bd9Sstevel@tonic-gate } 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * process msgid and msgstr pair for previous domain 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate if (inmsgstr) { 410*7c478bd9Sstevel@tonic-gate sortit(gmsgid, gmsgstr); 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate /* refresh msgid and msgstr buffer */ 414*7c478bd9Sstevel@tonic-gate if (inmsgstr || inmsgid) { 415*7c478bd9Sstevel@tonic-gate (void) memset(gmsgid, 0, gmsgid_size); 416*7c478bd9Sstevel@tonic-gate (void) memset(gmsgstr, 0, gmsgstr_size); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate if (indomain) { 420*7c478bd9Sstevel@tonic-gate /* multiple lines of domain */ 421*7c478bd9Sstevel@tonic-gate /* cancel the previous null termination */ 422*7c478bd9Sstevel@tonic-gate bufptr_index--; 423*7c478bd9Sstevel@tonic-gate } else { 424*7c478bd9Sstevel@tonic-gate p = linebufptr; 425*7c478bd9Sstevel@tonic-gate linebufptr = consume_whitespace( 426*7c478bd9Sstevel@tonic-gate linebufptr + DOMAIN_LEN); 427*7c478bd9Sstevel@tonic-gate (void) memset(gcurrent_domain, 0, 428*7c478bd9Sstevel@tonic-gate sizeof (gcurrent_domain)); 429*7c478bd9Sstevel@tonic-gate ln_size -= linebufptr - p; 430*7c478bd9Sstevel@tonic-gate bufptr = gcurrent_domain; 431*7c478bd9Sstevel@tonic-gate bufptr_index = 0; 432*7c478bd9Sstevel@tonic-gate } 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate indomain = 1; 435*7c478bd9Sstevel@tonic-gate inmsgid = 0; 436*7c478bd9Sstevel@tonic-gate inmsgstr = 0; 437*7c478bd9Sstevel@tonic-gate } /* if */ 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate load_buffer: 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * Now, fill up the buffer pointed by bufptr. 442*7c478bd9Sstevel@tonic-gate * At this point bufptr should point to one of 443*7c478bd9Sstevel@tonic-gate * msgid, msgptr, or current_domain. 444*7c478bd9Sstevel@tonic-gate * Otherwise, the entire line is ignored. 445*7c478bd9Sstevel@tonic-gate */ 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate if (!bufptr) { 448*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_SYNTAX_ERR), linenum); 449*7c478bd9Sstevel@tonic-gate continue; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (*linebufptr++ != L'\"') { 453*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_MISSING_QUOTE), linenum); 454*7c478bd9Sstevel@tonic-gate --linebufptr; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate quotefound = 0; 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate /* 459*7c478bd9Sstevel@tonic-gate * If there is not enough space in the buffer, 460*7c478bd9Sstevel@tonic-gate * increase buffer by ln_size by realloc. 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate ll = ln_size * mbcurmax; 463*7c478bd9Sstevel@tonic-gate if (bufptr == gmsgid) { 464*7c478bd9Sstevel@tonic-gate if (gmsgid_size < (bufptr_index + ll)) { 465*7c478bd9Sstevel@tonic-gate gmsgid = (char *)Xrealloc(gmsgid, 466*7c478bd9Sstevel@tonic-gate bufptr_index + ll); 467*7c478bd9Sstevel@tonic-gate bufptr = gmsgid; 468*7c478bd9Sstevel@tonic-gate gmsgid_size = bufptr_index + ll; 469*7c478bd9Sstevel@tonic-gate } 470*7c478bd9Sstevel@tonic-gate } else if (bufptr == gmsgstr) { 471*7c478bd9Sstevel@tonic-gate if (gmsgstr_size < (bufptr_index + ll)) { 472*7c478bd9Sstevel@tonic-gate gmsgstr = (char *)Xrealloc(gmsgstr, 473*7c478bd9Sstevel@tonic-gate bufptr_index + ll); 474*7c478bd9Sstevel@tonic-gate bufptr = gmsgstr; 475*7c478bd9Sstevel@tonic-gate gmsgstr_size = bufptr_index + ll; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate while (wc = *linebufptr++) { 480*7c478bd9Sstevel@tonic-gate switch (wc) { 481*7c478bd9Sstevel@tonic-gate case L'\n': 482*7c478bd9Sstevel@tonic-gate if (!quotefound) { 483*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_MISSING_QUOTE_AT_EOL), linenum); 484*7c478bd9Sstevel@tonic-gate } 485*7c478bd9Sstevel@tonic-gate break; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate case L'\"': 488*7c478bd9Sstevel@tonic-gate quotefound = 1; 489*7c478bd9Sstevel@tonic-gate break; 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate case L'\\': 492*7c478bd9Sstevel@tonic-gate if ((mb = expand_meta(&linebufptr)) != NULL) 493*7c478bd9Sstevel@tonic-gate bufptr[bufptr_index++] = mb; 494*7c478bd9Sstevel@tonic-gate break; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate default: 497*7c478bd9Sstevel@tonic-gate if ((n = wctomb(&bufptr[bufptr_index], wc)) > 0) 498*7c478bd9Sstevel@tonic-gate bufptr_index += n; 499*7c478bd9Sstevel@tonic-gate } /* switch */ 500*7c478bd9Sstevel@tonic-gate if (quotefound) { 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * Check if any remaining characters 503*7c478bd9Sstevel@tonic-gate * after closing quote. 504*7c478bd9Sstevel@tonic-gate */ 505*7c478bd9Sstevel@tonic-gate linebufptr = consume_whitespace(linebufptr); 506*7c478bd9Sstevel@tonic-gate if (*linebufptr != L'\n') { 507*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_INVALID_STRING), 508*7c478bd9Sstevel@tonic-gate linenum); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate break; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } /* while */ 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate bufptr[bufptr_index++] = '\0'; 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate (void) strcpy(msgfile, gcurrent_domain); 517*7c478bd9Sstevel@tonic-gate (void) strcat(msgfile, ".mo"); 518*7c478bd9Sstevel@tonic-gate } /* for(;;) */ 519*7c478bd9Sstevel@tonic-gate 520*7c478bd9Sstevel@tonic-gate if (inmsgstr) { 521*7c478bd9Sstevel@tonic-gate sortit(gmsgid, gmsgstr); 522*7c478bd9Sstevel@tonic-gate } 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate if (linebufhead) 525*7c478bd9Sstevel@tonic-gate free(linebufhead); 526*7c478bd9Sstevel@tonic-gate if (munmap(addr, statbuf.st_size) == -1) { 527*7c478bd9Sstevel@tonic-gate error(gettext(ERR_MUNMAP_FAILED), filename); 528*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 529*7c478bd9Sstevel@tonic-gate } 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate free(filename); 532*7c478bd9Sstevel@tonic-gate return; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate } /* read_psffm */ 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate /* 538*7c478bd9Sstevel@tonic-gate * Skip leading white spaces and tabs. 539*7c478bd9Sstevel@tonic-gate */ 540*7c478bd9Sstevel@tonic-gate static wchar_t * 541*7c478bd9Sstevel@tonic-gate consume_whitespace(wchar_t *buf) 542*7c478bd9Sstevel@tonic-gate { 543*7c478bd9Sstevel@tonic-gate wchar_t *bufptr = buf; 544*7c478bd9Sstevel@tonic-gate wchar_t c; 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate /* 547*7c478bd9Sstevel@tonic-gate * Skip leading white spaces. 548*7c478bd9Sstevel@tonic-gate */ 549*7c478bd9Sstevel@tonic-gate while ((c = *bufptr) != L'\0') { 550*7c478bd9Sstevel@tonic-gate if (c == L' ' || c == L'\t') { 551*7c478bd9Sstevel@tonic-gate bufptr++; 552*7c478bd9Sstevel@tonic-gate continue; 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate break; 555*7c478bd9Sstevel@tonic-gate } 556*7c478bd9Sstevel@tonic-gate return (bufptr); 557*7c478bd9Sstevel@tonic-gate } /* consume_white_space */ 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* 561*7c478bd9Sstevel@tonic-gate * handle escape sequences. 562*7c478bd9Sstevel@tonic-gate */ 563*7c478bd9Sstevel@tonic-gate static char 564*7c478bd9Sstevel@tonic-gate expand_meta(wchar_t **buf) 565*7c478bd9Sstevel@tonic-gate { 566*7c478bd9Sstevel@tonic-gate wchar_t wc = **buf; 567*7c478bd9Sstevel@tonic-gate char n; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate switch (wc) { 570*7c478bd9Sstevel@tonic-gate case L'"': 571*7c478bd9Sstevel@tonic-gate (*buf)++; 572*7c478bd9Sstevel@tonic-gate return ('\"'); 573*7c478bd9Sstevel@tonic-gate case L'\\': 574*7c478bd9Sstevel@tonic-gate (*buf)++; 575*7c478bd9Sstevel@tonic-gate return ('\\'); 576*7c478bd9Sstevel@tonic-gate case L'b': 577*7c478bd9Sstevel@tonic-gate (*buf)++; 578*7c478bd9Sstevel@tonic-gate return ('\b'); 579*7c478bd9Sstevel@tonic-gate case L'f': 580*7c478bd9Sstevel@tonic-gate (*buf)++; 581*7c478bd9Sstevel@tonic-gate return ('\f'); 582*7c478bd9Sstevel@tonic-gate case L'n': 583*7c478bd9Sstevel@tonic-gate (*buf)++; 584*7c478bd9Sstevel@tonic-gate return ('\n'); 585*7c478bd9Sstevel@tonic-gate case L'r': 586*7c478bd9Sstevel@tonic-gate (*buf)++; 587*7c478bd9Sstevel@tonic-gate return ('\r'); 588*7c478bd9Sstevel@tonic-gate case L't': 589*7c478bd9Sstevel@tonic-gate (*buf)++; 590*7c478bd9Sstevel@tonic-gate return ('\t'); 591*7c478bd9Sstevel@tonic-gate case L'v': 592*7c478bd9Sstevel@tonic-gate (*buf)++; 593*7c478bd9Sstevel@tonic-gate return ('\v'); 594*7c478bd9Sstevel@tonic-gate case L'a': 595*7c478bd9Sstevel@tonic-gate (*buf)++; 596*7c478bd9Sstevel@tonic-gate return ('\a'); 597*7c478bd9Sstevel@tonic-gate case L'\'': 598*7c478bd9Sstevel@tonic-gate (*buf)++; 599*7c478bd9Sstevel@tonic-gate return ('\''); 600*7c478bd9Sstevel@tonic-gate case L'?': 601*7c478bd9Sstevel@tonic-gate (*buf)++; 602*7c478bd9Sstevel@tonic-gate return ('\?'); 603*7c478bd9Sstevel@tonic-gate case L'0': 604*7c478bd9Sstevel@tonic-gate case L'1': 605*7c478bd9Sstevel@tonic-gate case L'2': 606*7c478bd9Sstevel@tonic-gate case L'3': 607*7c478bd9Sstevel@tonic-gate case L'4': 608*7c478bd9Sstevel@tonic-gate case L'5': 609*7c478bd9Sstevel@tonic-gate case L'6': 610*7c478bd9Sstevel@tonic-gate case L'7': 611*7c478bd9Sstevel@tonic-gate /* 612*7c478bd9Sstevel@tonic-gate * This case handles \ddd where ddd is octal number. 613*7c478bd9Sstevel@tonic-gate * There could be one, two, or three octal numbers. 614*7c478bd9Sstevel@tonic-gate */ 615*7c478bd9Sstevel@tonic-gate (*buf)++; 616*7c478bd9Sstevel@tonic-gate n = (char)(wc - L'0'); 617*7c478bd9Sstevel@tonic-gate wc = **buf; 618*7c478bd9Sstevel@tonic-gate if (wc >= L'0' && wc <= L'7') { 619*7c478bd9Sstevel@tonic-gate (*buf)++; 620*7c478bd9Sstevel@tonic-gate n = 8*n + (char)(wc - L'0'); 621*7c478bd9Sstevel@tonic-gate wc = **buf; 622*7c478bd9Sstevel@tonic-gate if (wc >= L'0' && wc <= L'7') { 623*7c478bd9Sstevel@tonic-gate (*buf)++; 624*7c478bd9Sstevel@tonic-gate n = 8*n + (char)(wc - L'0'); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate return (n); 628*7c478bd9Sstevel@tonic-gate default: 629*7c478bd9Sstevel@tonic-gate return (NULL); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate } /* expand_meta */ 632*7c478bd9Sstevel@tonic-gate 633*7c478bd9Sstevel@tonic-gate /* 634*7c478bd9Sstevel@tonic-gate * Finds the head of the current domain linked list and 635*7c478bd9Sstevel@tonic-gate * call insert_message() to insert msgid and msgstr pair 636*7c478bd9Sstevel@tonic-gate * to the linked list. 637*7c478bd9Sstevel@tonic-gate */ 638*7c478bd9Sstevel@tonic-gate static void 639*7c478bd9Sstevel@tonic-gate sortit(char *msgid, char *msgstr) 640*7c478bd9Sstevel@tonic-gate { 641*7c478bd9Sstevel@tonic-gate struct domain_struct *dom; 642*7c478bd9Sstevel@tonic-gate 643*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 644*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 645*7c478bd9Sstevel@tonic-gate "==> sortit(), domain=<%s> msgid=<%s> msgstr=<%s>\n", 646*7c478bd9Sstevel@tonic-gate gcurrent_domain, msgid, msgstr); 647*7c478bd9Sstevel@tonic-gate #endif 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate /* 650*7c478bd9Sstevel@tonic-gate * If "-o filename" is specified, then all "domain" directive 651*7c478bd9Sstevel@tonic-gate * are ignored and, all messages will be stored in domain 652*7c478bd9Sstevel@tonic-gate * whose name is filename. 653*7c478bd9Sstevel@tonic-gate */ 654*7c478bd9Sstevel@tonic-gate if (oflag) { 655*7c478bd9Sstevel@tonic-gate dom = find_domain_node(outfile); 656*7c478bd9Sstevel@tonic-gate } else { 657*7c478bd9Sstevel@tonic-gate dom = find_domain_node(gcurrent_domain); 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate insert_message(dom, msgid, msgstr); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate /* 664*7c478bd9Sstevel@tonic-gate * This routine inserts message in the current domain message list. 665*7c478bd9Sstevel@tonic-gate * It is inserted in ascending order. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate static void 668*7c478bd9Sstevel@tonic-gate insert_message(struct domain_struct *dom, 669*7c478bd9Sstevel@tonic-gate char *msgid, char *msgstr) 670*7c478bd9Sstevel@tonic-gate { 671*7c478bd9Sstevel@tonic-gate struct msg_chain *p1; 672*7c478bd9Sstevel@tonic-gate struct msg_chain *node, *prev_node; 673*7c478bd9Sstevel@tonic-gate int b; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate /* 676*7c478bd9Sstevel@tonic-gate * Find the optimal starting search position. 677*7c478bd9Sstevel@tonic-gate * The starting search position is either the first node 678*7c478bd9Sstevel@tonic-gate * or the current_elem of domain. 679*7c478bd9Sstevel@tonic-gate * The current_elem is the pointer to the node which 680*7c478bd9Sstevel@tonic-gate * is most recently accessed in domain. 681*7c478bd9Sstevel@tonic-gate */ 682*7c478bd9Sstevel@tonic-gate if (dom->current_elem != NULL) { 683*7c478bd9Sstevel@tonic-gate b = strcmp(msgid, dom->current_elem->msgid); 684*7c478bd9Sstevel@tonic-gate if (b == 0) { 685*7c478bd9Sstevel@tonic-gate if (verbose) 686*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_DUP_MSG), 687*7c478bd9Sstevel@tonic-gate msgid, msgid_linenum); 688*7c478bd9Sstevel@tonic-gate return; 689*7c478bd9Sstevel@tonic-gate } else if (b > 0) { /* to implement descending order */ 690*7c478bd9Sstevel@tonic-gate p1 = dom->first_elem; 691*7c478bd9Sstevel@tonic-gate } else { 692*7c478bd9Sstevel@tonic-gate p1 = dom->current_elem; 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate } else { 695*7c478bd9Sstevel@tonic-gate p1 = dom->first_elem; 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate 698*7c478bd9Sstevel@tonic-gate /* 699*7c478bd9Sstevel@tonic-gate * search msgid insert position in the list 700*7c478bd9Sstevel@tonic-gate * Search starts from the node pointed by p1. 701*7c478bd9Sstevel@tonic-gate */ 702*7c478bd9Sstevel@tonic-gate prev_node = NULL; 703*7c478bd9Sstevel@tonic-gate while (p1) { 704*7c478bd9Sstevel@tonic-gate b = strcmp(msgid, p1->msgid); 705*7c478bd9Sstevel@tonic-gate if (b == 0) { 706*7c478bd9Sstevel@tonic-gate if (verbose) 707*7c478bd9Sstevel@tonic-gate warning(gettext(WARN_DUP_MSG), 708*7c478bd9Sstevel@tonic-gate msgid, msgid_linenum); 709*7c478bd9Sstevel@tonic-gate return; 710*7c478bd9Sstevel@tonic-gate } else if (b < 0) { /* to implement descending order */ 711*7c478bd9Sstevel@tonic-gate /* move to the next node */ 712*7c478bd9Sstevel@tonic-gate prev_node = p1; 713*7c478bd9Sstevel@tonic-gate p1 = p1->next; 714*7c478bd9Sstevel@tonic-gate } else { 715*7c478bd9Sstevel@tonic-gate /* insert a new msg node */ 716*7c478bd9Sstevel@tonic-gate node = (struct msg_chain *) 717*7c478bd9Sstevel@tonic-gate Xmalloc(sizeof (struct msg_chain)); 718*7c478bd9Sstevel@tonic-gate node->next = p1; 719*7c478bd9Sstevel@tonic-gate node->msgid = Xstrdup(msgid); 720*7c478bd9Sstevel@tonic-gate node->msgstr = Xstrdup(msgstr); 721*7c478bd9Sstevel@tonic-gate 722*7c478bd9Sstevel@tonic-gate if (prev_node) { 723*7c478bd9Sstevel@tonic-gate prev_node->next = node; 724*7c478bd9Sstevel@tonic-gate } else { 725*7c478bd9Sstevel@tonic-gate dom->first_elem = node; 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate dom->current_elem = node; 728*7c478bd9Sstevel@tonic-gate return; 729*7c478bd9Sstevel@tonic-gate } 730*7c478bd9Sstevel@tonic-gate } /* while */ 731*7c478bd9Sstevel@tonic-gate 732*7c478bd9Sstevel@tonic-gate /* 733*7c478bd9Sstevel@tonic-gate * msgid is smaller than any of msgid in the list or 734*7c478bd9Sstevel@tonic-gate * list is empty. 735*7c478bd9Sstevel@tonic-gate * Therefore, append it. 736*7c478bd9Sstevel@tonic-gate */ 737*7c478bd9Sstevel@tonic-gate node = (struct msg_chain *) 738*7c478bd9Sstevel@tonic-gate Xmalloc(sizeof (struct msg_chain)); 739*7c478bd9Sstevel@tonic-gate node->next = NULL; 740*7c478bd9Sstevel@tonic-gate node->msgid = Xstrdup(msgid); 741*7c478bd9Sstevel@tonic-gate node->msgstr = Xstrdup(msgstr); 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate if (prev_node) { 744*7c478bd9Sstevel@tonic-gate prev_node->next = node; 745*7c478bd9Sstevel@tonic-gate } else { 746*7c478bd9Sstevel@tonic-gate dom->first_elem = node; 747*7c478bd9Sstevel@tonic-gate } 748*7c478bd9Sstevel@tonic-gate dom->current_elem = node; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate return; 751*7c478bd9Sstevel@tonic-gate 752*7c478bd9Sstevel@tonic-gate } /* insert_message */ 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate /* 756*7c478bd9Sstevel@tonic-gate * This routine will find head of the linked list for the given 757*7c478bd9Sstevel@tonic-gate * domain_name. This looks up cache entry first and if cache misses, 758*7c478bd9Sstevel@tonic-gate * scans the list. 759*7c478bd9Sstevel@tonic-gate * If not found, then create a new node. 760*7c478bd9Sstevel@tonic-gate */ 761*7c478bd9Sstevel@tonic-gate static struct domain_struct * 762*7c478bd9Sstevel@tonic-gate find_domain_node(char *domain_name) 763*7c478bd9Sstevel@tonic-gate { 764*7c478bd9Sstevel@tonic-gate struct domain_struct *p1; 765*7c478bd9Sstevel@tonic-gate struct domain_struct *node; 766*7c478bd9Sstevel@tonic-gate struct domain_struct *prev_node; 767*7c478bd9Sstevel@tonic-gate int b; 768*7c478bd9Sstevel@tonic-gate 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate /* for perfomance, check cache 'last_used_domain' */ 771*7c478bd9Sstevel@tonic-gate if (last_used_domain) { 772*7c478bd9Sstevel@tonic-gate b = strcmp(domain_name, last_used_domain->domain); 773*7c478bd9Sstevel@tonic-gate if (b == 0) { 774*7c478bd9Sstevel@tonic-gate return (last_used_domain); 775*7c478bd9Sstevel@tonic-gate } else if (b < 0) { 776*7c478bd9Sstevel@tonic-gate p1 = first_domain; 777*7c478bd9Sstevel@tonic-gate } else { 778*7c478bd9Sstevel@tonic-gate p1 = last_used_domain; 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate } else { 781*7c478bd9Sstevel@tonic-gate p1 = first_domain; 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate prev_node = NULL; 785*7c478bd9Sstevel@tonic-gate while (p1) { 786*7c478bd9Sstevel@tonic-gate b = strcmp(domain_name, p1->domain); 787*7c478bd9Sstevel@tonic-gate if (b == 0) { 788*7c478bd9Sstevel@tonic-gate /* node found */ 789*7c478bd9Sstevel@tonic-gate last_used_domain = p1; 790*7c478bd9Sstevel@tonic-gate return (p1); 791*7c478bd9Sstevel@tonic-gate } else if (b > 0) { 792*7c478bd9Sstevel@tonic-gate /* move to the next node */ 793*7c478bd9Sstevel@tonic-gate prev_node = p1; 794*7c478bd9Sstevel@tonic-gate p1 = p1->next; 795*7c478bd9Sstevel@tonic-gate } else { 796*7c478bd9Sstevel@tonic-gate /* insert a new domain node */ 797*7c478bd9Sstevel@tonic-gate node = (struct domain_struct *) 798*7c478bd9Sstevel@tonic-gate Xmalloc(sizeof (struct domain_struct)); 799*7c478bd9Sstevel@tonic-gate node->next = p1; 800*7c478bd9Sstevel@tonic-gate node->domain = Xstrdup(domain_name); 801*7c478bd9Sstevel@tonic-gate node->first_elem = NULL; 802*7c478bd9Sstevel@tonic-gate node->current_elem = NULL; 803*7c478bd9Sstevel@tonic-gate if (prev_node) { 804*7c478bd9Sstevel@tonic-gate /* insert the node in the middle */ 805*7c478bd9Sstevel@tonic-gate prev_node->next = node; 806*7c478bd9Sstevel@tonic-gate } else { 807*7c478bd9Sstevel@tonic-gate /* node inserted is the smallest */ 808*7c478bd9Sstevel@tonic-gate first_domain = node; 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate last_used_domain = node; 811*7c478bd9Sstevel@tonic-gate return (node); 812*7c478bd9Sstevel@tonic-gate } 813*7c478bd9Sstevel@tonic-gate } /* while */ 814*7c478bd9Sstevel@tonic-gate 815*7c478bd9Sstevel@tonic-gate /* 816*7c478bd9Sstevel@tonic-gate * domain_name is larger than any of domain name in the list or 817*7c478bd9Sstevel@tonic-gate * list is empty. 818*7c478bd9Sstevel@tonic-gate */ 819*7c478bd9Sstevel@tonic-gate node = (struct domain_struct *) 820*7c478bd9Sstevel@tonic-gate Xmalloc(sizeof (struct domain_struct)); 821*7c478bd9Sstevel@tonic-gate node->next = NULL; 822*7c478bd9Sstevel@tonic-gate node->domain = Xstrdup(domain_name); 823*7c478bd9Sstevel@tonic-gate node->first_elem = NULL; 824*7c478bd9Sstevel@tonic-gate node->current_elem = NULL; 825*7c478bd9Sstevel@tonic-gate if (prev_node) { 826*7c478bd9Sstevel@tonic-gate /* domain list is not empty */ 827*7c478bd9Sstevel@tonic-gate prev_node->next = node; 828*7c478bd9Sstevel@tonic-gate } else { 829*7c478bd9Sstevel@tonic-gate /* domain list is empty */ 830*7c478bd9Sstevel@tonic-gate first_domain = node; 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate last_used_domain = node; 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate return (node); 835*7c478bd9Sstevel@tonic-gate 836*7c478bd9Sstevel@tonic-gate } /* find_domain_node */ 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate 839*7c478bd9Sstevel@tonic-gate /* 840*7c478bd9Sstevel@tonic-gate * binary_compute() is used for pre-computing a binary search. 841*7c478bd9Sstevel@tonic-gate */ 842*7c478bd9Sstevel@tonic-gate static int 843*7c478bd9Sstevel@tonic-gate binary_compute(int i, int j, int *more, int *less) 844*7c478bd9Sstevel@tonic-gate { 845*7c478bd9Sstevel@tonic-gate int k; 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate if (i > j) { 848*7c478bd9Sstevel@tonic-gate return (LEAFINDICATOR); 849*7c478bd9Sstevel@tonic-gate } 850*7c478bd9Sstevel@tonic-gate k = (i + j) / 2; 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate less[k] = binary_compute(i, k - 1, more, less); 853*7c478bd9Sstevel@tonic-gate more[k] = binary_compute(k + 1, j, more, less); 854*7c478bd9Sstevel@tonic-gate 855*7c478bd9Sstevel@tonic-gate return (k); 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate } /* binary_compute */ 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate /* 861*7c478bd9Sstevel@tonic-gate * Write all domain data to file. 862*7c478bd9Sstevel@tonic-gate * Each domain will create one file. 863*7c478bd9Sstevel@tonic-gate */ 864*7c478bd9Sstevel@tonic-gate static void 865*7c478bd9Sstevel@tonic-gate output_all_mo_files(void) 866*7c478bd9Sstevel@tonic-gate { 867*7c478bd9Sstevel@tonic-gate struct domain_struct *p; 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate p = first_domain; 870*7c478bd9Sstevel@tonic-gate while (p) { 871*7c478bd9Sstevel@tonic-gate /* 872*7c478bd9Sstevel@tonic-gate * generate message object file only if there is 873*7c478bd9Sstevel@tonic-gate * at least one element. 874*7c478bd9Sstevel@tonic-gate */ 875*7c478bd9Sstevel@tonic-gate if (p->first_elem) { 876*7c478bd9Sstevel@tonic-gate output_one_mo_file(p); 877*7c478bd9Sstevel@tonic-gate } 878*7c478bd9Sstevel@tonic-gate p = p->next; 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate return; 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate } /* output_all_mo_files */ 883*7c478bd9Sstevel@tonic-gate 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate /* 886*7c478bd9Sstevel@tonic-gate * Write one domain data list to file. 887*7c478bd9Sstevel@tonic-gate */ 888*7c478bd9Sstevel@tonic-gate static void 889*7c478bd9Sstevel@tonic-gate output_one_mo_file(struct domain_struct *dom) 890*7c478bd9Sstevel@tonic-gate { 891*7c478bd9Sstevel@tonic-gate FILE *fp; 892*7c478bd9Sstevel@tonic-gate struct msg_chain *p; 893*7c478bd9Sstevel@tonic-gate int message_count; 894*7c478bd9Sstevel@tonic-gate int string_count_msgid; 895*7c478bd9Sstevel@tonic-gate int string_count_msg; 896*7c478bd9Sstevel@tonic-gate int msgid_index = 0; 897*7c478bd9Sstevel@tonic-gate int msgstr_index = 0; 898*7c478bd9Sstevel@tonic-gate int *less, *more; 899*7c478bd9Sstevel@tonic-gate int i; 900*7c478bd9Sstevel@tonic-gate char fname [TEXTDOMAINMAX+1]; 901*7c478bd9Sstevel@tonic-gate 902*7c478bd9Sstevel@tonic-gate if (!dom || !dom->first_elem) 903*7c478bd9Sstevel@tonic-gate return; 904*7c478bd9Sstevel@tonic-gate 905*7c478bd9Sstevel@tonic-gate /* 906*7c478bd9Sstevel@tonic-gate * If -o flag is specified, then file name is used as domain name. 907*7c478bd9Sstevel@tonic-gate * If not, ".mo" is appended to the domain name. 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate (void) strcpy(fname, dom->domain); 910*7c478bd9Sstevel@tonic-gate if (!oflag) { 911*7c478bd9Sstevel@tonic-gate (void) strcat(fname, ".mo"); 912*7c478bd9Sstevel@tonic-gate } 913*7c478bd9Sstevel@tonic-gate fp = fopen(fname, "w"); 914*7c478bd9Sstevel@tonic-gate if (fp == NULL) { 915*7c478bd9Sstevel@tonic-gate error(gettext(ERR_OPEN_FAILED), fname); 916*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 917*7c478bd9Sstevel@tonic-gate } 918*7c478bd9Sstevel@tonic-gate 919*7c478bd9Sstevel@tonic-gate /* compute offsets and counts */ 920*7c478bd9Sstevel@tonic-gate message_count = 0; 921*7c478bd9Sstevel@tonic-gate p = dom->first_elem; 922*7c478bd9Sstevel@tonic-gate while (p) { 923*7c478bd9Sstevel@tonic-gate p->msgid_offset = msgid_index; 924*7c478bd9Sstevel@tonic-gate p->msgstr_offset = msgstr_index; 925*7c478bd9Sstevel@tonic-gate msgid_index += strlen(p->msgid) + 1; 926*7c478bd9Sstevel@tonic-gate msgstr_index += strlen(p->msgstr) + 1; 927*7c478bd9Sstevel@tonic-gate message_count++; 928*7c478bd9Sstevel@tonic-gate p = p->next; 929*7c478bd9Sstevel@tonic-gate } 930*7c478bd9Sstevel@tonic-gate 931*7c478bd9Sstevel@tonic-gate /* 932*7c478bd9Sstevel@tonic-gate * Fill up less and more entries to be used for binary search. 933*7c478bd9Sstevel@tonic-gate */ 934*7c478bd9Sstevel@tonic-gate string_count_msgid = msgid_index; 935*7c478bd9Sstevel@tonic-gate string_count_msg = msgstr_index; 936*7c478bd9Sstevel@tonic-gate less = (int *)Xcalloc(message_count, sizeof (int)); 937*7c478bd9Sstevel@tonic-gate more = (int *)Xcalloc(message_count, sizeof (int)); 938*7c478bd9Sstevel@tonic-gate 939*7c478bd9Sstevel@tonic-gate (void) binary_compute(0, message_count - 1, more, less); 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 942*7c478bd9Sstevel@tonic-gate { 943*7c478bd9Sstevel@tonic-gate int i; 944*7c478bd9Sstevel@tonic-gate for (i = 0; i < message_count; i++) { 945*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 946*7c478bd9Sstevel@tonic-gate " less[%2d]=%2d, more[%2d]=%2d\n", 947*7c478bd9Sstevel@tonic-gate i, less[i], i, more[i]); 948*7c478bd9Sstevel@tonic-gate } 949*7c478bd9Sstevel@tonic-gate } 950*7c478bd9Sstevel@tonic-gate #endif 951*7c478bd9Sstevel@tonic-gate 952*7c478bd9Sstevel@tonic-gate /* 953*7c478bd9Sstevel@tonic-gate * write out the message object file. 954*7c478bd9Sstevel@tonic-gate * The middle one is the first message to check by gettext(). 955*7c478bd9Sstevel@tonic-gate */ 956*7c478bd9Sstevel@tonic-gate i = (message_count - 1) / 2; 957*7c478bd9Sstevel@tonic-gate (void) fwrite(&i, sizeof (int), 1, fp); 958*7c478bd9Sstevel@tonic-gate (void) fwrite(&message_count, sizeof (int), 1, fp); 959*7c478bd9Sstevel@tonic-gate (void) fwrite(&string_count_msgid, sizeof (int), 1, fp); 960*7c478bd9Sstevel@tonic-gate (void) fwrite(&string_count_msg, sizeof (int), 1, fp); 961*7c478bd9Sstevel@tonic-gate i = MSG_STRUCT_SIZE * message_count; 962*7c478bd9Sstevel@tonic-gate (void) fwrite(&i, sizeof (int), 1, fp); 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate /* march through linked list and write out all nodes. */ 965*7c478bd9Sstevel@tonic-gate i = 0; 966*7c478bd9Sstevel@tonic-gate p = dom->first_elem; 967*7c478bd9Sstevel@tonic-gate while (p) { /* put out message struct */ 968*7c478bd9Sstevel@tonic-gate (void) fwrite(&less[i], sizeof (int), 1, fp); 969*7c478bd9Sstevel@tonic-gate (void) fwrite(&more[i], sizeof (int), 1, fp); 970*7c478bd9Sstevel@tonic-gate (void) fwrite(&p->msgid_offset, sizeof (int), 1, fp); 971*7c478bd9Sstevel@tonic-gate (void) fwrite(&p->msgstr_offset, sizeof (int), 1, fp); 972*7c478bd9Sstevel@tonic-gate i++; 973*7c478bd9Sstevel@tonic-gate p = p->next; 974*7c478bd9Sstevel@tonic-gate } 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate /* put out message id strings */ 977*7c478bd9Sstevel@tonic-gate p = dom->first_elem; 978*7c478bd9Sstevel@tonic-gate while (p) { 979*7c478bd9Sstevel@tonic-gate (void) fwrite(p->msgid, strlen(p->msgid)+1, 1, fp); 980*7c478bd9Sstevel@tonic-gate p = p->next; 981*7c478bd9Sstevel@tonic-gate } 982*7c478bd9Sstevel@tonic-gate 983*7c478bd9Sstevel@tonic-gate /* put out message strings */ 984*7c478bd9Sstevel@tonic-gate p = dom->first_elem; 985*7c478bd9Sstevel@tonic-gate while (p) { 986*7c478bd9Sstevel@tonic-gate (void) fwrite(p->msgstr, strlen(p->msgstr)+1, 1, fp); 987*7c478bd9Sstevel@tonic-gate p = p->next; 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate (void) fclose(fp); 991*7c478bd9Sstevel@tonic-gate free(less); 992*7c478bd9Sstevel@tonic-gate free(more); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate return; 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate } /* output_one_mo_file */ 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate 999*7c478bd9Sstevel@tonic-gate /* 1000*7c478bd9Sstevel@tonic-gate * read one line from *mbuf, 1001*7c478bd9Sstevel@tonic-gate * skip preceding whitespaces, 1002*7c478bd9Sstevel@tonic-gate * convert the line to wide characters, 1003*7c478bd9Sstevel@tonic-gate * place the wide characters into *bufhead, and 1004*7c478bd9Sstevel@tonic-gate * return the number of wide characters placed. 1005*7c478bd9Sstevel@tonic-gate * 1006*7c478bd9Sstevel@tonic-gate * INPUT: 1007*7c478bd9Sstevel@tonic-gate * **bufhead - address of a variable that is the pointer 1008*7c478bd9Sstevel@tonic-gate * to wchar_t. 1009*7c478bd9Sstevel@tonic-gate * The variable should been initialized to NULL. 1010*7c478bd9Sstevel@tonic-gate * **mbuf - address of a variable that is the pointer 1011*7c478bd9Sstevel@tonic-gate * to char. 1012*7c478bd9Sstevel@tonic-gate * The pointer should point to the memory mmapped to 1013*7c478bd9Sstevel@tonic-gate * the file to input. 1014*7c478bd9Sstevel@tonic-gate * **fsize - address of a size_t variable that contains 1015*7c478bd9Sstevel@tonic-gate * the size of unread bytes in the file to input. 1016*7c478bd9Sstevel@tonic-gate * OUTPUT: 1017*7c478bd9Sstevel@tonic-gate * return - the number of wide characters placed. 1018*7c478bd9Sstevel@tonic-gate * **bufhead - _mbsntowcs allocates the buffer to store 1019*7c478bd9Sstevel@tonic-gate * one line in wchar_t from *mbuf and sets the address 1020*7c478bd9Sstevel@tonic-gate * to *bufhead. 1021*7c478bd9Sstevel@tonic-gate * **mbuf - _mbsntowcs reads one line from *mbuf and sets *mbuf 1022*7c478bd9Sstevel@tonic-gate * to the beginning of the next line. 1023*7c478bd9Sstevel@tonic-gate * **fsize - *fsize will be set to the size of the unread 1024*7c478bd9Sstevel@tonic-gate * bytes in the file. 1025*7c478bd9Sstevel@tonic-gate */ 1026*7c478bd9Sstevel@tonic-gate static size_t 1027*7c478bd9Sstevel@tonic-gate _mbsntowcs(wchar_t **bufhead, char **mbuf, size_t *fsize) 1028*7c478bd9Sstevel@tonic-gate { 1029*7c478bd9Sstevel@tonic-gate wchar_t *tp, *th; 1030*7c478bd9Sstevel@tonic-gate wchar_t wc; 1031*7c478bd9Sstevel@tonic-gate size_t tbufsize = LINE_SIZE; 1032*7c478bd9Sstevel@tonic-gate size_t ttbufsize, nc; 1033*7c478bd9Sstevel@tonic-gate char *pc = *mbuf; 1034*7c478bd9Sstevel@tonic-gate int nb; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate if (*fsize == 0) { 1037*7c478bd9Sstevel@tonic-gate /* eof */ 1038*7c478bd9Sstevel@tonic-gate return (0); 1039*7c478bd9Sstevel@tonic-gate } 1040*7c478bd9Sstevel@tonic-gate 1041*7c478bd9Sstevel@tonic-gate th = (wchar_t *)Xmalloc(sizeof (wchar_t) * tbufsize); 1042*7c478bd9Sstevel@tonic-gate nc = tbufsize; 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate /* skip preceding whitespaces */ 1045*7c478bd9Sstevel@tonic-gate while ((*pc != '\0')) { 1046*7c478bd9Sstevel@tonic-gate if ((*pc == ' ') || (*pc == '\t')) { 1047*7c478bd9Sstevel@tonic-gate pc++; 1048*7c478bd9Sstevel@tonic-gate (*fsize)--; 1049*7c478bd9Sstevel@tonic-gate } else { 1050*7c478bd9Sstevel@tonic-gate break; 1051*7c478bd9Sstevel@tonic-gate } 1052*7c478bd9Sstevel@tonic-gate } 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate tp = th; 1055*7c478bd9Sstevel@tonic-gate while (*fsize > 0) { 1056*7c478bd9Sstevel@tonic-gate nb = mbtowc(&wc, pc, mbcurmax); 1057*7c478bd9Sstevel@tonic-gate if (nb == -1) { 1058*7c478bd9Sstevel@tonic-gate return ((size_t)-1); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate if (*pc == '\n') { 1062*7c478bd9Sstevel@tonic-gate /* found eol */ 1063*7c478bd9Sstevel@tonic-gate if (nc <= 1) { 1064*7c478bd9Sstevel@tonic-gate /* 1065*7c478bd9Sstevel@tonic-gate * not enough buffer 1066*7c478bd9Sstevel@tonic-gate * at least 2 more bytes are required for 1067*7c478bd9Sstevel@tonic-gate * L'\n' and L'\0' 1068*7c478bd9Sstevel@tonic-gate */ 1069*7c478bd9Sstevel@tonic-gate ttbufsize = tbufsize + 2; 1070*7c478bd9Sstevel@tonic-gate th = (wchar_t *)Xrealloc(th, 1071*7c478bd9Sstevel@tonic-gate sizeof (wchar_t) * ttbufsize); 1072*7c478bd9Sstevel@tonic-gate tp = th + tbufsize - nc; 1073*7c478bd9Sstevel@tonic-gate tbufsize = ttbufsize; 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate *tp++ = L'\n'; 1076*7c478bd9Sstevel@tonic-gate *tp++ = L'\0'; 1077*7c478bd9Sstevel@tonic-gate pc += nb; 1078*7c478bd9Sstevel@tonic-gate *fsize -= nb; 1079*7c478bd9Sstevel@tonic-gate *mbuf = pc; 1080*7c478bd9Sstevel@tonic-gate *bufhead = th; 1081*7c478bd9Sstevel@tonic-gate return ((size_t)(tp - th)); 1082*7c478bd9Sstevel@tonic-gate } 1083*7c478bd9Sstevel@tonic-gate if (nc == 0) { 1084*7c478bd9Sstevel@tonic-gate ttbufsize = tbufsize + LINE_SIZE; 1085*7c478bd9Sstevel@tonic-gate th = (wchar_t *)Xrealloc(th, 1086*7c478bd9Sstevel@tonic-gate sizeof (wchar_t) * ttbufsize); 1087*7c478bd9Sstevel@tonic-gate tp = th + tbufsize; 1088*7c478bd9Sstevel@tonic-gate nc = LINE_SIZE; 1089*7c478bd9Sstevel@tonic-gate tbufsize = ttbufsize; 1090*7c478bd9Sstevel@tonic-gate } 1091*7c478bd9Sstevel@tonic-gate *tp++ = wc; 1092*7c478bd9Sstevel@tonic-gate nc--; 1093*7c478bd9Sstevel@tonic-gate pc += nb; 1094*7c478bd9Sstevel@tonic-gate *fsize -= nb; 1095*7c478bd9Sstevel@tonic-gate } /* while */ 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate /* 1098*7c478bd9Sstevel@tonic-gate * At this point, the input file has been consumed, 1099*7c478bd9Sstevel@tonic-gate * but there is no ending '\n'; we add it to 1100*7c478bd9Sstevel@tonic-gate * the output file. 1101*7c478bd9Sstevel@tonic-gate */ 1102*7c478bd9Sstevel@tonic-gate if (nc <= 1) { 1103*7c478bd9Sstevel@tonic-gate /* 1104*7c478bd9Sstevel@tonic-gate * not enough buffer 1105*7c478bd9Sstevel@tonic-gate * at least 2 more bytes are required for 1106*7c478bd9Sstevel@tonic-gate * L'\n' and L'\0' 1107*7c478bd9Sstevel@tonic-gate */ 1108*7c478bd9Sstevel@tonic-gate ttbufsize = tbufsize + 2; 1109*7c478bd9Sstevel@tonic-gate th = (wchar_t *)Xrealloc(th, 1110*7c478bd9Sstevel@tonic-gate sizeof (wchar_t) * ttbufsize); 1111*7c478bd9Sstevel@tonic-gate tp = th + tbufsize - nc; 1112*7c478bd9Sstevel@tonic-gate tbufsize = ttbufsize; 1113*7c478bd9Sstevel@tonic-gate } 1114*7c478bd9Sstevel@tonic-gate *tp++ = L'\n'; 1115*7c478bd9Sstevel@tonic-gate *tp++ = L'\0'; 1116*7c478bd9Sstevel@tonic-gate *mbuf = pc; 1117*7c478bd9Sstevel@tonic-gate *bufhead = th; 1118*7c478bd9Sstevel@tonic-gate return ((size_t)(tp - th)); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate /* 1123*7c478bd9Sstevel@tonic-gate * This is debug function. Not compiled in the final executable. 1124*7c478bd9Sstevel@tonic-gate */ 1125*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1126*7c478bd9Sstevel@tonic-gate static void 1127*7c478bd9Sstevel@tonic-gate printlist(void) 1128*7c478bd9Sstevel@tonic-gate { 1129*7c478bd9Sstevel@tonic-gate struct domain_struct *p; 1130*7c478bd9Sstevel@tonic-gate struct msg_chain *m; 1131*7c478bd9Sstevel@tonic-gate 1132*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n=== Printing contents of all domains ===\n"); 1133*7c478bd9Sstevel@tonic-gate p = first_domain; 1134*7c478bd9Sstevel@tonic-gate while (p) { 1135*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "domain name = <%s>\n", p->domain); 1136*7c478bd9Sstevel@tonic-gate m = p->first_elem; 1137*7c478bd9Sstevel@tonic-gate while (m) { 1138*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, " msgid=<%s>, msgstr=<%s>\n", 1139*7c478bd9Sstevel@tonic-gate m->msgid, m->msgstr); 1140*7c478bd9Sstevel@tonic-gate m = m->next; 1141*7c478bd9Sstevel@tonic-gate } 1142*7c478bd9Sstevel@tonic-gate p = p->next; 1143*7c478bd9Sstevel@tonic-gate } 1144*7c478bd9Sstevel@tonic-gate } /* printlist */ 1145*7c478bd9Sstevel@tonic-gate #endif 1146