1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate * 26*0Sstevel@tonic-gate * sgsmsg generates several message files from an input template file. Messages 27*0Sstevel@tonic-gate * are constructed for use with gettext(3i) - the default - or catgets(3c). The 28*0Sstevel@tonic-gate * files generate are: 29*0Sstevel@tonic-gate * 30*0Sstevel@tonic-gate * msg.h a header file containing definitions for each message. The -h 31*0Sstevel@tonic-gate * option triggers the creation of these definitions and specifies 32*0Sstevel@tonic-gate * the name to use. 33*0Sstevel@tonic-gate * 34*0Sstevel@tonic-gate * msg.c a data array of message strings. The msg.h definitions are 35*0Sstevel@tonic-gate * offsets into this array. The -d option triggers the creation of 36*0Sstevel@tonic-gate * these definitions and specifies the name to use. 37*0Sstevel@tonic-gate * 38*0Sstevel@tonic-gate * messages a message file suitable for catgets(3c) or gettext(3i) use. The 39*0Sstevel@tonic-gate * -m option triggers this output and specifies the filename to be 40*0Sstevel@tonic-gate * used. 41*0Sstevel@tonic-gate * 42*0Sstevel@tonic-gate * The template file is processed based on the first character of each line: 43*0Sstevel@tonic-gate * 44*0Sstevel@tonic-gate * # or $ entries are copied (as is) to the message file (messages). 45*0Sstevel@tonic-gate * 46*0Sstevel@tonic-gate * @ token(s) entries are translated. Two translations are possible dependent 47*0Sstevel@tonic-gate * on whether one or more tokens are supplied: 48*0Sstevel@tonic-gate * 49*0Sstevel@tonic-gate * A single token is interpreted as one of two reserved message 50*0Sstevel@tonic-gate * output indicators, or a message identifier. The reserved output 51*0Sstevel@tonic-gate * indicator _START_ enables output to the message file - Note that 52*0Sstevel@tonic-gate * the occurance of any other @ token will also enable message 53*0Sstevel@tonic-gate * output. The reserved output indicator _END_ disables output to 54*0Sstevel@tonic-gate * the message file. The use of these two indicators provides for 55*0Sstevel@tonic-gate * only those message strings that require translation to be output 56*0Sstevel@tonic-gate * to the message file. 57*0Sstevel@tonic-gate * 58*0Sstevel@tonic-gate * Besides the reserved output indicators, a single token is taken 59*0Sstevel@tonic-gate * to be a message identifier which will be subsituted for a 60*0Sstevel@tonic-gate * `setid' for catgets(3c) output, or a `domain' name for 61*0Sstevel@tonic-gate * gettext(3i) output. This value is determine by substituting the 62*0Sstevel@tonic-gate * token for the associated definition found in the message 63*0Sstevel@tonic-gate * identifier file (specified with the -i option). 64*0Sstevel@tonic-gate * 65*0Sstevel@tonic-gate * Multiple tokens are taken to be a message definition followed by 66*0Sstevel@tonic-gate * the associated message string. The message string is copied to 67*0Sstevel@tonic-gate * the data array being built in msg.c. The index into this array 68*0Sstevel@tonic-gate * becomes the `message' identifier created in the msg.h file. 69*0Sstevel@tonic-gate */ 70*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate #include <fcntl.h> 73*0Sstevel@tonic-gate #include <stdlib.h> 74*0Sstevel@tonic-gate #include <stdio.h> 75*0Sstevel@tonic-gate #include <unistd.h> 76*0Sstevel@tonic-gate #include <limits.h> 77*0Sstevel@tonic-gate #include <string.h> 78*0Sstevel@tonic-gate #include <ctype.h> 79*0Sstevel@tonic-gate #include <errno.h> 80*0Sstevel@tonic-gate #include <sys/param.h> 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate #include <sgs.h> 83*0Sstevel@tonic-gate #include <string_table.h> 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * Define any error message strings. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate static const char 89*0Sstevel@tonic-gate * Errmsg_malt = "sgsmsg: file %s: line %d: malformed input " 90*0Sstevel@tonic-gate "at line\n", 91*0Sstevel@tonic-gate * Errmsg_nmem = "sgsmsg: memory allocation failed: %s\n", 92*0Sstevel@tonic-gate * Errmsg_opne = "sgsmsg: file %s: open failed: %s\n", 93*0Sstevel@tonic-gate * Errmsg_wrte = "sgsmsg: file %s: write failed: %s\n", 94*0Sstevel@tonic-gate * Errmsg_read = "sgsmsg: file %s: read failed %s\n", 95*0Sstevel@tonic-gate * Errmsg_stnw = "sgsmsg: st_new(): failed: %s\n", 96*0Sstevel@tonic-gate * Errmsg_stin = "sgsmsg: Str_tbl insert failed: %s\n", 97*0Sstevel@tonic-gate * Errmsg_mnfn = "sgsmsg: message not found in Str_tbl: %s\n", 98*0Sstevel@tonic-gate * Errmsg_use = "usage: sgsmsg [-clv] [-d mesgdata] [-h mesgdefs] " 99*0Sstevel@tonic-gate "[-m messages] [-n name] [-i mesgident] file ...\n"; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * Define all output filenames and associated descriptors. 103*0Sstevel@tonic-gate */ 104*0Sstevel@tonic-gate static FILE *fddefs, *fddata, *fdmsgs, *fdmids, *fddesc; 105*0Sstevel@tonic-gate static char *fldefs, *fldata, *flmsgs, *flmids, *fldesc; 106*0Sstevel@tonic-gate static FILE *fdlint; 107*0Sstevel@tonic-gate static char fllint[MAXPATHLEN]; 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate static uint_t vflag; /* verbose flag */ 110*0Sstevel@tonic-gate static Str_tbl *stp; /* string table */ 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * Define any default strings. 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate static const char 116*0Sstevel@tonic-gate *nmlint = "/tmp/sgsmsg.lint", 117*0Sstevel@tonic-gate *interface = "sgs_msg", 118*0Sstevel@tonic-gate *start = "_START_", 119*0Sstevel@tonic-gate *end = "_END_"; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate /* 122*0Sstevel@tonic-gate * Define any default flags and data items. 123*0Sstevel@tonic-gate */ 124*0Sstevel@tonic-gate static int cflag = 0, lflag = 0, prtmsgs = 0, line, ptr = 1, msgid = 0; 125*0Sstevel@tonic-gate static char *mesgid = 0, *setid = 0, *domain = 0; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate typedef struct msg_string { 128*0Sstevel@tonic-gate char *ms_defn; 129*0Sstevel@tonic-gate char *ms_message; 130*0Sstevel@tonic-gate struct msg_string *ms_next; 131*0Sstevel@tonic-gate } msg_string; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate static msg_string *msg_head; 134*0Sstevel@tonic-gate static msg_string *msg_tail; 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate /* 137*0Sstevel@tonic-gate * message_append() is responsible for both inserting strings into 138*0Sstevel@tonic-gate * the master Str_tbl as well as maintaining a list of the 139*0Sstevel@tonic-gate * DEFINITIONS associated with each string. 140*0Sstevel@tonic-gate * 141*0Sstevel@tonic-gate * The list of strings is traversed at the end once the full 142*0Sstevel@tonic-gate * Str_tbl has been constructed - and string offsets can be 143*0Sstevel@tonic-gate * assigned. 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate static void 146*0Sstevel@tonic-gate message_append(const char *defn, const char *message) 147*0Sstevel@tonic-gate { 148*0Sstevel@tonic-gate msg_string *msg; 149*0Sstevel@tonic-gate if ((msg = calloc(sizeof (msg_string), 1)) == 0) { 150*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 151*0Sstevel@tonic-gate exit(1); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate if (stp == 0) { 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * Initialize string table 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate if ((stp = st_new(FLG_STNEW_COMPRESS)) == 0) { 158*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_stnw, strerror(errno)); 159*0Sstevel@tonic-gate exit(1); 160*0Sstevel@tonic-gate } 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate if ((msg->ms_defn = strdup(defn)) == 0) { 165*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 166*0Sstevel@tonic-gate exit(1); 167*0Sstevel@tonic-gate } 168*0Sstevel@tonic-gate if ((msg->ms_message = strdup(message)) == 0) { 169*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 170*0Sstevel@tonic-gate exit(1); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate if (st_insert(stp, msg->ms_message) == -1) { 174*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_stin, 175*0Sstevel@tonic-gate message); 176*0Sstevel@tonic-gate exit(1); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate if (msg_head == 0) { 180*0Sstevel@tonic-gate msg_head = msg_tail = msg; 181*0Sstevel@tonic-gate return; 182*0Sstevel@tonic-gate } 183*0Sstevel@tonic-gate msg_tail->ms_next = msg; 184*0Sstevel@tonic-gate msg_tail = msg; 185*0Sstevel@tonic-gate } 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate * Initialize a setid value. Given a setid definition determine its numeric 189*0Sstevel@tonic-gate * value from the specified message identifier file (specified with the -i 190*0Sstevel@tonic-gate * option). Return a pointer to the numeric string. 191*0Sstevel@tonic-gate */ 192*0Sstevel@tonic-gate static int 193*0Sstevel@tonic-gate getmesgid(char *id) 194*0Sstevel@tonic-gate { 195*0Sstevel@tonic-gate char *buffer, *token, *_mesgid = 0, *_setid = 0, *_domain = 0; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * If we're being asked to interpret a message id but the user didn't 199*0Sstevel@tonic-gate * provide the required message identifier file (-i option) we're in 200*0Sstevel@tonic-gate * trouble. 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate if (flmids == 0) { 203*0Sstevel@tonic-gate (void) fprintf(stderr, "sgsmsg: file %s: line %d: mesgid %s: " 204*0Sstevel@tonic-gate "unable to process mesgid\n\t" 205*0Sstevel@tonic-gate "no message identifier file specified " 206*0Sstevel@tonic-gate "(see -i option)\n", fldesc, line, id); 207*0Sstevel@tonic-gate return (1); 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if ((buffer = malloc(LINE_MAX)) == 0) { 211*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 212*0Sstevel@tonic-gate return (1); 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate /* 216*0Sstevel@tonic-gate * Read the message identifier file and locate the required mesgid. 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate rewind(fdmids); 219*0Sstevel@tonic-gate while (fgets(buffer, LINE_MAX, fdmids) != NULL) { 220*0Sstevel@tonic-gate if ((token = strstr(buffer, id)) == NULL) 221*0Sstevel@tonic-gate continue; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* 224*0Sstevel@tonic-gate * Establish individual strings for the mesgid, setid and domain 225*0Sstevel@tonic-gate * values. 226*0Sstevel@tonic-gate */ 227*0Sstevel@tonic-gate _mesgid = token; 228*0Sstevel@tonic-gate while (!(isspace(*token))) 229*0Sstevel@tonic-gate token++; 230*0Sstevel@tonic-gate *token++ = 0; 231*0Sstevel@tonic-gate 232*0Sstevel@tonic-gate while (isspace(*token)) 233*0Sstevel@tonic-gate token++; 234*0Sstevel@tonic-gate _setid = token; 235*0Sstevel@tonic-gate while (!(isspace(*token))) 236*0Sstevel@tonic-gate token++; 237*0Sstevel@tonic-gate *token++ = 0; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate while (isspace(*token)) 240*0Sstevel@tonic-gate token++; 241*0Sstevel@tonic-gate _domain = token; 242*0Sstevel@tonic-gate while (!(isspace(*token))) 243*0Sstevel@tonic-gate token++; 244*0Sstevel@tonic-gate *token = 0; 245*0Sstevel@tonic-gate break; 246*0Sstevel@tonic-gate } 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate /* 249*0Sstevel@tonic-gate * Did we find a match? 250*0Sstevel@tonic-gate */ 251*0Sstevel@tonic-gate if ((_mesgid == 0) || (_setid == 0) || (_domain == 0)) { 252*0Sstevel@tonic-gate (void) fprintf(stderr, "sgsmsg: file %s: line %d: mesgid %s: " 253*0Sstevel@tonic-gate "unable to process mesgid\n\t" 254*0Sstevel@tonic-gate "identifier does not exist in file %s\n", 255*0Sstevel@tonic-gate fldesc, line, id, flmids); 256*0Sstevel@tonic-gate return (1); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * Have we been here before? 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate if (mesgid) { 263*0Sstevel@tonic-gate if (cflag == 1) { 264*0Sstevel@tonic-gate /* 265*0Sstevel@tonic-gate * If we're being asked to process more than one mesgid 266*0Sstevel@tonic-gate * warn the user that only one mesgid can be used for 267*0Sstevel@tonic-gate * the catgets(3c) call. 268*0Sstevel@tonic-gate */ 269*0Sstevel@tonic-gate (void) fprintf(stderr, "sgsmsg: file %s: line %d: " 270*0Sstevel@tonic-gate "setid %s: warning: multiple mesgids " 271*0Sstevel@tonic-gate "encountered\n\t" 272*0Sstevel@tonic-gate "last setting used in messaging code\n", 273*0Sstevel@tonic-gate fldesc, line, id); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate mesgid = _mesgid; 278*0Sstevel@tonic-gate setid = _setid; 279*0Sstevel@tonic-gate domain = _domain; 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* 282*0Sstevel@tonic-gate * Generate the message file output (insure output flag is enabled). 283*0Sstevel@tonic-gate */ 284*0Sstevel@tonic-gate if (prtmsgs != -1) 285*0Sstevel@tonic-gate prtmsgs = 1; 286*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1)) { 287*0Sstevel@tonic-gate if (cflag == 1) { 288*0Sstevel@tonic-gate if (fprintf(fdmsgs, "$quote \"\n$set %s\n", 289*0Sstevel@tonic-gate setid) < 0) { 290*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, flmsgs, 291*0Sstevel@tonic-gate strerror(errno)); 292*0Sstevel@tonic-gate return (1); 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate } else { 295*0Sstevel@tonic-gate if (fprintf(fdmsgs, "domain\t\"%s\"\n", domain) < 0) { 296*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, flmsgs, 297*0Sstevel@tonic-gate strerror(errno)); 298*0Sstevel@tonic-gate return (1); 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* 304*0Sstevel@tonic-gate * For catgets(3c) output generate a setid definition in the message 305*0Sstevel@tonic-gate * definition file. 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate if (fddefs && (cflag == 1) && 308*0Sstevel@tonic-gate (fprintf(fddefs, "#define\t%s\t%s\n\n", mesgid, setid) < 0)) { 309*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 310*0Sstevel@tonic-gate return (1); 311*0Sstevel@tonic-gate } 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate return (0); 314*0Sstevel@tonic-gate } 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate /* 318*0Sstevel@tonic-gate * Dump contents of String Table to standard out 319*0Sstevel@tonic-gate */ 320*0Sstevel@tonic-gate static void 321*0Sstevel@tonic-gate dump_stringtab(Str_tbl *stp) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate uint_t i; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) { 326*0Sstevel@tonic-gate (void) printf("uncompressed strings: %d\n", 327*0Sstevel@tonic-gate stp->st_fullstringsize); 328*0Sstevel@tonic-gate return; 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate for (i = 0; i < stp->st_hbckcnt; i++) { 333*0Sstevel@tonic-gate Str_hash *sthash; 334*0Sstevel@tonic-gate (void) printf("Bucket: [%3d]\n", i); 335*0Sstevel@tonic-gate for (sthash = stp->st_hashbcks[i]; sthash; 336*0Sstevel@tonic-gate sthash = sthash->hi_next) { 337*0Sstevel@tonic-gate uint_t stroff; 338*0Sstevel@tonic-gate stroff = sthash->hi_mstr->sm_stlen - sthash->hi_stlen; 339*0Sstevel@tonic-gate if (stroff == 0) { 340*0Sstevel@tonic-gate (void) printf(" %2d %s <master>\n", 341*0Sstevel@tonic-gate sthash->hi_refcnt, 342*0Sstevel@tonic-gate sthash->hi_mstr->sm_str); 343*0Sstevel@tonic-gate } else { 344*0Sstevel@tonic-gate const char *str; 345*0Sstevel@tonic-gate str = &sthash->hi_mstr->sm_str[stroff]; 346*0Sstevel@tonic-gate (void) printf(" %2d %s <suffix of> -> %s\n", 347*0Sstevel@tonic-gate sthash->hi_refcnt, 348*0Sstevel@tonic-gate str, sthash->hi_mstr->sm_str); 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate } 352*0Sstevel@tonic-gate (void) printf("fullstringsize: %d compressed: %d\n", 353*0Sstevel@tonic-gate stp->st_fullstringsize, stp->st_stringsize); 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate /* 356*0Sstevel@tonic-gate * Initialize the message definition header file stream. 357*0Sstevel@tonic-gate */ 358*0Sstevel@tonic-gate static int 359*0Sstevel@tonic-gate init_defs(void) 360*0Sstevel@tonic-gate { 361*0Sstevel@tonic-gate static char guard[FILENAME_MAX + 6]; 362*0Sstevel@tonic-gate char *optr; 363*0Sstevel@tonic-gate const char *iptr, *_ptr; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate /* 366*0Sstevel@tonic-gate * Establish a header guard name using the files basename. 367*0Sstevel@tonic-gate */ 368*0Sstevel@tonic-gate for (iptr = 0, _ptr = fldefs; _ptr && (*_ptr != '\0'); _ptr++) { 369*0Sstevel@tonic-gate if (*_ptr == '/') 370*0Sstevel@tonic-gate iptr = _ptr + 1; 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate if (iptr == 0) 373*0Sstevel@tonic-gate iptr = fldefs; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate optr = guard; 376*0Sstevel@tonic-gate for (*optr++ = '_'; iptr && (*iptr != '\0'); iptr++, optr++) { 377*0Sstevel@tonic-gate if (*iptr == '.') { 378*0Sstevel@tonic-gate *optr++ = '_'; 379*0Sstevel@tonic-gate *optr++ = 'D'; 380*0Sstevel@tonic-gate *optr++ = 'O'; 381*0Sstevel@tonic-gate *optr++ = 'T'; 382*0Sstevel@tonic-gate *optr = '_'; 383*0Sstevel@tonic-gate } else 384*0Sstevel@tonic-gate *optr = toupper(*iptr); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate if (fprintf(fddefs, "#ifndef\t%s\n#define\t%s\n\n", guard, guard) < 0) { 388*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 389*0Sstevel@tonic-gate return (1); 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate if (fprintf(fddefs, "#ifndef\t__lint\n\n") < 0) { 393*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 394*0Sstevel@tonic-gate return (1); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate /* 398*0Sstevel@tonic-gate * add "typedef int Msg;" 399*0Sstevel@tonic-gate */ 400*0Sstevel@tonic-gate if (fprintf(fddefs, "typedef int\tMsg;\n\n") < 0) { 401*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 402*0Sstevel@tonic-gate return (1); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate /* 406*0Sstevel@tonic-gate * If the associated data array is global define a prototype. 407*0Sstevel@tonic-gate * Define a macro to access the array elements. 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate if (lflag == 0) { 410*0Sstevel@tonic-gate if (fprintf(fddefs, "extern\tconst char\t__%s[];\n\n", 411*0Sstevel@tonic-gate interface) < 0) { 412*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, 413*0Sstevel@tonic-gate strerror(errno)); 414*0Sstevel@tonic-gate return (1); 415*0Sstevel@tonic-gate } 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate if (fprintf(fddefs, "#define\tMSG_ORIG(x)\t&__%s[x]\n\n", 418*0Sstevel@tonic-gate interface) < 0) { 419*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 420*0Sstevel@tonic-gate return (1); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate 423*0Sstevel@tonic-gate /* 424*0Sstevel@tonic-gate * Generate a prototype to access the associated data array. 425*0Sstevel@tonic-gate */ 426*0Sstevel@tonic-gate if (fprintf(fddefs, "extern\tconst char *\t_%s(Msg);\n\n", 427*0Sstevel@tonic-gate interface) < 0) { 428*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 429*0Sstevel@tonic-gate return (1); 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate if (fprintf(fddefs, "#define\tMSG_INTL(x)\t_%s(x)\n\n", 432*0Sstevel@tonic-gate interface) < 0) { 433*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 434*0Sstevel@tonic-gate return (1); 435*0Sstevel@tonic-gate } 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate return (0); 438*0Sstevel@tonic-gate } 439*0Sstevel@tonic-gate 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate /* 442*0Sstevel@tonic-gate * Finish the message definition header file. 443*0Sstevel@tonic-gate */ 444*0Sstevel@tonic-gate static int 445*0Sstevel@tonic-gate fini_defs(void) 446*0Sstevel@tonic-gate { 447*0Sstevel@tonic-gate if (fprintf(fddefs, "\n#else\t/* __lint */\n\n") < 0) { 448*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 449*0Sstevel@tonic-gate return (1); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate /* 453*0Sstevel@tonic-gate * When __lint is defined, Msg is a char *. This allows lint to 454*0Sstevel@tonic-gate * check our format strings against it's arguments. 455*0Sstevel@tonic-gate */ 456*0Sstevel@tonic-gate if (fprintf(fddefs, "\ntypedef char *\tMsg;\n\n") < 0) { 457*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 458*0Sstevel@tonic-gate return (1); 459*0Sstevel@tonic-gate } 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate if (fprintf(fddefs, "extern\tconst char *\t_%s(Msg);\n\n", 462*0Sstevel@tonic-gate interface) < 0) { 463*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 464*0Sstevel@tonic-gate return (1); 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate 467*0Sstevel@tonic-gate if (lflag == 0) { 468*0Sstevel@tonic-gate if (fprintf(fddefs, "extern\tconst char\t__%s[];\n\n", 469*0Sstevel@tonic-gate interface) < 0) { 470*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, 471*0Sstevel@tonic-gate strerror(errno)); 472*0Sstevel@tonic-gate return (1); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate if (fprintf(fddefs, 477*0Sstevel@tonic-gate "#define MSG_ORIG(x)\tx\n#define MSG_INTL(x)\tx\n") < 0) { 478*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 479*0Sstevel@tonic-gate return (1); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * Copy the temporary lint defs file into the new header. 484*0Sstevel@tonic-gate */ 485*0Sstevel@tonic-gate if (fdlint) { 486*0Sstevel@tonic-gate long size; 487*0Sstevel@tonic-gate char *buf; 488*0Sstevel@tonic-gate 489*0Sstevel@tonic-gate size = ftell(fdlint); 490*0Sstevel@tonic-gate (void) rewind(fdlint); 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate if ((buf = malloc(size)) == 0) { 493*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 494*0Sstevel@tonic-gate return (1); 495*0Sstevel@tonic-gate } 496*0Sstevel@tonic-gate if (fread(buf, size, 1, fdlint) == 0) { 497*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_read, fllint, 498*0Sstevel@tonic-gate strerror(errno)); 499*0Sstevel@tonic-gate return (1); 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate if (fwrite(buf, size, 1, fddefs) == 0) { 502*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, 503*0Sstevel@tonic-gate strerror(errno)); 504*0Sstevel@tonic-gate return (1); 505*0Sstevel@tonic-gate } 506*0Sstevel@tonic-gate (void) free(buf); 507*0Sstevel@tonic-gate } 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate if (fprintf(fddefs, "\n#endif\t/* __lint */\n") < 0) { 510*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 511*0Sstevel@tonic-gate return (1); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate if (fprintf(fddefs, "\n#endif\n") < 0) { 515*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno)); 516*0Sstevel@tonic-gate return (1); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate return (0); 520*0Sstevel@tonic-gate } 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate 523*0Sstevel@tonic-gate /* 524*0Sstevel@tonic-gate * The entire messaging file has been scanned - and all strings have been 525*0Sstevel@tonic-gate * inserted into the string_table. We can now walk the message queue 526*0Sstevel@tonic-gate * and create the '#define <DEFN>' for each string - with the strings 527*0Sstevel@tonic-gate * assigned offset into the string_table. 528*0Sstevel@tonic-gate */ 529*0Sstevel@tonic-gate static int 530*0Sstevel@tonic-gate output_defs(void) 531*0Sstevel@tonic-gate { 532*0Sstevel@tonic-gate msg_string *msg; 533*0Sstevel@tonic-gate uint_t stbufsize; 534*0Sstevel@tonic-gate char *stbuf; 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate stbufsize = st_getstrtab_sz(stp); 537*0Sstevel@tonic-gate if ((stbuf = malloc(stbufsize)) == 0) { 538*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 539*0Sstevel@tonic-gate exit(1); 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate (void) st_setstrbuf(stp, stbuf, stbufsize); 542*0Sstevel@tonic-gate for (msg = msg_head; msg; msg = msg->ms_next) { 543*0Sstevel@tonic-gate uint_t stoff; 544*0Sstevel@tonic-gate if ((st_setstring(stp, msg->ms_message, &stoff)) == -1) { 545*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_mnfn, msg->ms_message); 546*0Sstevel@tonic-gate return (1); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate if (fprintf(fddefs, "\n#define\t%s\t%d\n", 549*0Sstevel@tonic-gate msg->ms_defn, stoff) < 0) { 550*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 551*0Sstevel@tonic-gate fldefs, strerror(errno)); 552*0Sstevel@tonic-gate return (1); 553*0Sstevel@tonic-gate } 554*0Sstevel@tonic-gate if (fddefs && fprintf(fddefs, "#define\t%s_SIZE\t%d\n", 555*0Sstevel@tonic-gate msg->ms_defn, strlen(msg->ms_message)) < 0) { 556*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 557*0Sstevel@tonic-gate fldefs, strerror(errno)); 558*0Sstevel@tonic-gate return (1); 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate return (0); 562*0Sstevel@tonic-gate } 563*0Sstevel@tonic-gate 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate /* 566*0Sstevel@tonic-gate * Finish off the data structure definition. 567*0Sstevel@tonic-gate */ 568*0Sstevel@tonic-gate static int 569*0Sstevel@tonic-gate output_data(void) 570*0Sstevel@tonic-gate { 571*0Sstevel@tonic-gate uint_t stbufsize; 572*0Sstevel@tonic-gate uint_t ndx; 573*0Sstevel@tonic-gate uint_t column = 1; 574*0Sstevel@tonic-gate const char *stbuf; 575*0Sstevel@tonic-gate const char *fmtstr; 576*0Sstevel@tonic-gate 577*0Sstevel@tonic-gate stbufsize = st_getstrtab_sz(stp); 578*0Sstevel@tonic-gate stbuf = st_getstrbuf(stp); 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate assert(stbuf); 581*0Sstevel@tonic-gate 582*0Sstevel@tonic-gate /* 583*0Sstevel@tonic-gate * Determine from the local flag whether the data declaration should 584*0Sstevel@tonic-gate * be static. 585*0Sstevel@tonic-gate */ 586*0Sstevel@tonic-gate if (lflag) 587*0Sstevel@tonic-gate fmtstr = (const char *)"static const"; 588*0Sstevel@tonic-gate else 589*0Sstevel@tonic-gate fmtstr = (const char *)"const"; 590*0Sstevel@tonic-gate 591*0Sstevel@tonic-gate if (fprintf(fddata, "\n%s char __%s[%d] = { ", 592*0Sstevel@tonic-gate fmtstr, interface, stbufsize) < 0) { 593*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldata, strerror(errno)); 594*0Sstevel@tonic-gate return (1); 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate 597*0Sstevel@tonic-gate for (ndx = 0; ndx < (stbufsize - 1); ndx++) { 598*0Sstevel@tonic-gate if (column == 1) { 599*0Sstevel@tonic-gate if (fddata && fprintf(fddata, 600*0Sstevel@tonic-gate "\n/* %4d */ 0x%.2x,", ndx, 601*0Sstevel@tonic-gate (unsigned char)stbuf[ndx]) < 0) { 602*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 603*0Sstevel@tonic-gate fldata, strerror(errno)); 604*0Sstevel@tonic-gate return (1); 605*0Sstevel@tonic-gate } 606*0Sstevel@tonic-gate } else { 607*0Sstevel@tonic-gate if (fddata && fprintf(fddata, " 0x%.2x,", 608*0Sstevel@tonic-gate (unsigned char)stbuf[ndx]) < 0) { 609*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 610*0Sstevel@tonic-gate fldata, strerror(errno)); 611*0Sstevel@tonic-gate return (1); 612*0Sstevel@tonic-gate } 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate if (column++ == 10) 616*0Sstevel@tonic-gate column = 1; 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate 619*0Sstevel@tonic-gate if (column == 1) 620*0Sstevel@tonic-gate fmtstr = "\n\t0x%.2x };\n"; 621*0Sstevel@tonic-gate else 622*0Sstevel@tonic-gate fmtstr = " 0x%.2x };\n"; 623*0Sstevel@tonic-gate 624*0Sstevel@tonic-gate if (fprintf(fddata, fmtstr, (unsigned char)stbuf[stbufsize - 1]) < 0) { 625*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, fldata, strerror(errno)); 626*0Sstevel@tonic-gate return (1); 627*0Sstevel@tonic-gate } 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate return (0); 630*0Sstevel@tonic-gate } 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate static int 633*0Sstevel@tonic-gate file() 634*0Sstevel@tonic-gate { 635*0Sstevel@tonic-gate char buffer[LINE_MAX], * token; 636*0Sstevel@tonic-gate uint_t bufsize; 637*0Sstevel@tonic-gate char *token_buffer; 638*0Sstevel@tonic-gate int escape = 0; 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate if ((token_buffer = malloc(LINE_MAX)) == 0) { 641*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_nmem, strerror(errno)); 642*0Sstevel@tonic-gate return (1); 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate bufsize = LINE_MAX; 645*0Sstevel@tonic-gate 646*0Sstevel@tonic-gate line = 1; 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate while ((token = fgets(buffer, LINE_MAX, fddesc)) != NULL) { 649*0Sstevel@tonic-gate char defn[PATH_MAX], * _defn, * str; 650*0Sstevel@tonic-gate int len; 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate switch (*token) { 653*0Sstevel@tonic-gate case '#': 654*0Sstevel@tonic-gate case '$': 655*0Sstevel@tonic-gate if (escape) { 656*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_malt, fldesc, 657*0Sstevel@tonic-gate line); 658*0Sstevel@tonic-gate return (1); 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate /* 662*0Sstevel@tonic-gate * If a msgid has been output a msgstr must follow 663*0Sstevel@tonic-gate * before we digest the new token. A msgid is only set 664*0Sstevel@tonic-gate * if fdmsgs is in use. 665*0Sstevel@tonic-gate */ 666*0Sstevel@tonic-gate if (msgid) { 667*0Sstevel@tonic-gate msgid = 0; 668*0Sstevel@tonic-gate if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) { 669*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 670*0Sstevel@tonic-gate flmsgs, strerror(errno)); 671*0Sstevel@tonic-gate return (1); 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * Pass lines directly through to the output message 677*0Sstevel@tonic-gate * file. 678*0Sstevel@tonic-gate */ 679*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1)) { 680*0Sstevel@tonic-gate char comment; 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate if (cflag == 0) 683*0Sstevel@tonic-gate comment = '#'; 684*0Sstevel@tonic-gate else 685*0Sstevel@tonic-gate comment = '$'; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate if (fprintf(fdmsgs, "%c%s", comment, 688*0Sstevel@tonic-gate ++token) < 0) { 689*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 690*0Sstevel@tonic-gate flmsgs, strerror(errno)); 691*0Sstevel@tonic-gate return (1); 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate } 694*0Sstevel@tonic-gate break; 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate case '@': 697*0Sstevel@tonic-gate if (escape) { 698*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_malt, fldesc, 699*0Sstevel@tonic-gate line); 700*0Sstevel@tonic-gate return (1); 701*0Sstevel@tonic-gate } 702*0Sstevel@tonic-gate 703*0Sstevel@tonic-gate /* 704*0Sstevel@tonic-gate * If a msgid has been output a msgstr must follow 705*0Sstevel@tonic-gate * before we digest the new token. 706*0Sstevel@tonic-gate */ 707*0Sstevel@tonic-gate if (msgid) { 708*0Sstevel@tonic-gate msgid = 0; 709*0Sstevel@tonic-gate if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) { 710*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 711*0Sstevel@tonic-gate flmsgs, strerror(errno)); 712*0Sstevel@tonic-gate return (1); 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate } 715*0Sstevel@tonic-gate 716*0Sstevel@tonic-gate /* 717*0Sstevel@tonic-gate * Determine whether we have one or more tokens. 718*0Sstevel@tonic-gate */ 719*0Sstevel@tonic-gate token++; 720*0Sstevel@tonic-gate while (isspace(*token)) /* rid any whitespace */ 721*0Sstevel@tonic-gate token++; 722*0Sstevel@tonic-gate _defn = token; /* definition start */ 723*0Sstevel@tonic-gate while (!(isspace(*token))) 724*0Sstevel@tonic-gate token++; 725*0Sstevel@tonic-gate *token++ = 0; 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate while (isspace(*token)) /* rid any whitespace */ 728*0Sstevel@tonic-gate token++; 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate /* 731*0Sstevel@tonic-gate * Determine whether the single token is one of the 732*0Sstevel@tonic-gate * reserved message output delimiters otherwise 733*0Sstevel@tonic-gate * translate it as a message identifier. 734*0Sstevel@tonic-gate */ 735*0Sstevel@tonic-gate if (*token == 0) { 736*0Sstevel@tonic-gate if (strcmp(_defn, start) == 0) 737*0Sstevel@tonic-gate prtmsgs = 1; 738*0Sstevel@tonic-gate else if (strcmp(_defn, end) == 0) 739*0Sstevel@tonic-gate prtmsgs = -1; 740*0Sstevel@tonic-gate else if (getmesgid(_defn) == 1) 741*0Sstevel@tonic-gate return (1); 742*0Sstevel@tonic-gate break; 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate /* 746*0Sstevel@tonic-gate * Multiple tokens are translated by taking the first 747*0Sstevel@tonic-gate * token as the message definition, and the rest of the 748*0Sstevel@tonic-gate * line as the message itself. A message line ending 749*0Sstevel@tonic-gate * with an escape ('\') is expected to be continued on 750*0Sstevel@tonic-gate * the next line. 751*0Sstevel@tonic-gate */ 752*0Sstevel@tonic-gate if (prtmsgs != -1) 753*0Sstevel@tonic-gate prtmsgs = 1; 754*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1)) { 755*0Sstevel@tonic-gate /* 756*0Sstevel@tonic-gate * For catgets(3c) make sure a message 757*0Sstevel@tonic-gate * identifier has been established (this is 758*0Sstevel@tonic-gate * normally a domain for gettext(3i), but for 759*0Sstevel@tonic-gate * sgsmsg use this could be argued as being 760*0Sstevel@tonic-gate * redundent). Also make sure that the message 761*0Sstevel@tonic-gate * definitions haven't exceeeded the maximum 762*0Sstevel@tonic-gate * value allowed by gencat(1) before generating 763*0Sstevel@tonic-gate * any message file entries. 764*0Sstevel@tonic-gate */ 765*0Sstevel@tonic-gate if (cflag == 1) { 766*0Sstevel@tonic-gate if (setid == 0) { 767*0Sstevel@tonic-gate (void) fprintf(stderr, "file " 768*0Sstevel@tonic-gate "%s: no message identifier " 769*0Sstevel@tonic-gate "has been established\n", 770*0Sstevel@tonic-gate fldesc); 771*0Sstevel@tonic-gate return (1); 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate if (ptr > NL_MSGMAX) { 774*0Sstevel@tonic-gate (void) fprintf(stderr, "file " 775*0Sstevel@tonic-gate "%s: message definition " 776*0Sstevel@tonic-gate "(%d) exceeds allowable " 777*0Sstevel@tonic-gate "limit (NL_MSGMAX)\n", 778*0Sstevel@tonic-gate fldesc, ptr); 779*0Sstevel@tonic-gate return (1); 780*0Sstevel@tonic-gate } 781*0Sstevel@tonic-gate } 782*0Sstevel@tonic-gate 783*0Sstevel@tonic-gate /* 784*0Sstevel@tonic-gate * For catgets(3c) write the definition and the 785*0Sstevel@tonic-gate * message string to the message file. For 786*0Sstevel@tonic-gate * gettext(3i) write the message string as a 787*0Sstevel@tonic-gate * mesgid - indicate a mesgid has been output 788*0Sstevel@tonic-gate * so that a msgstr can follow. 789*0Sstevel@tonic-gate */ 790*0Sstevel@tonic-gate if (cflag == 1) { 791*0Sstevel@tonic-gate if (fprintf(fdmsgs, "%d\t%s", ptr, 792*0Sstevel@tonic-gate token) < 0) { 793*0Sstevel@tonic-gate (void) fprintf(stderr, 794*0Sstevel@tonic-gate Errmsg_wrte, flmsgs, 795*0Sstevel@tonic-gate strerror(errno)); 796*0Sstevel@tonic-gate return (1); 797*0Sstevel@tonic-gate } 798*0Sstevel@tonic-gate } else { 799*0Sstevel@tonic-gate if (fprintf(fdmsgs, "msgid\t\"") < 0) { 800*0Sstevel@tonic-gate (void) fprintf(stderr, 801*0Sstevel@tonic-gate Errmsg_wrte, flmsgs, 802*0Sstevel@tonic-gate strerror(errno)); 803*0Sstevel@tonic-gate return (1); 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate msgid = 1; 806*0Sstevel@tonic-gate } 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate /* 810*0Sstevel@tonic-gate * The message itself is a quoted string as this makes 811*0Sstevel@tonic-gate * embedding spaces at the start (or the end) of the 812*0Sstevel@tonic-gate * string very easy. 813*0Sstevel@tonic-gate */ 814*0Sstevel@tonic-gate if (*token != '"') { 815*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_malt, fldesc, 816*0Sstevel@tonic-gate line); 817*0Sstevel@tonic-gate return (1); 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate 820*0Sstevel@tonic-gate (void) strcpy(defn, _defn); 821*0Sstevel@tonic-gate 822*0Sstevel@tonic-gate /* 823*0Sstevel@tonic-gate * Write the tag to the lint definitions. 824*0Sstevel@tonic-gate */ 825*0Sstevel@tonic-gate if (fdlint) { 826*0Sstevel@tonic-gate if (fprintf(fdlint, "\n#define\t%s\t", 827*0Sstevel@tonic-gate _defn) < 0) { 828*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 829*0Sstevel@tonic-gate fllint, strerror(errno)); 830*0Sstevel@tonic-gate return (1); 831*0Sstevel@tonic-gate } 832*0Sstevel@tonic-gate } 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gate len = 0; 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate /* 837*0Sstevel@tonic-gate * Write each character of the message string to the 838*0Sstevel@tonic-gate * data array. Translate any escaped characters - use 839*0Sstevel@tonic-gate * the same specially recognized characters as defined 840*0Sstevel@tonic-gate * by gencat(1). 841*0Sstevel@tonic-gate */ 842*0Sstevel@tonic-gate message: 843*0Sstevel@tonic-gate if (*token == '"') { 844*0Sstevel@tonic-gate if (fdlint && 845*0Sstevel@tonic-gate (fprintf(fdlint, "%c", *token) < 0)) { 846*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 847*0Sstevel@tonic-gate fllint, strerror(errno)); 848*0Sstevel@tonic-gate return (1); 849*0Sstevel@tonic-gate } 850*0Sstevel@tonic-gate token++; 851*0Sstevel@tonic-gate } 852*0Sstevel@tonic-gate while (*token) { 853*0Sstevel@tonic-gate char _token; 854*0Sstevel@tonic-gate 855*0Sstevel@tonic-gate if ((*token == '\\') && (escape == 0)) { 856*0Sstevel@tonic-gate escape = 1; 857*0Sstevel@tonic-gate if (fdlint && (*(token + 1) != '\n') && 858*0Sstevel@tonic-gate fprintf(fdlint, "%c", *token) < 0) { 859*0Sstevel@tonic-gate (void) fprintf(stderr, 860*0Sstevel@tonic-gate Errmsg_wrte, fllint, 861*0Sstevel@tonic-gate strerror(errno)); 862*0Sstevel@tonic-gate return (1); 863*0Sstevel@tonic-gate } 864*0Sstevel@tonic-gate token++; 865*0Sstevel@tonic-gate continue; 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate if (escape) { 868*0Sstevel@tonic-gate if (*token == 'n') 869*0Sstevel@tonic-gate _token = '\n'; 870*0Sstevel@tonic-gate else if (*token == 't') 871*0Sstevel@tonic-gate _token = '\t'; 872*0Sstevel@tonic-gate else if (*token == 'v') 873*0Sstevel@tonic-gate _token = '\v'; 874*0Sstevel@tonic-gate else if (*token == 'b') 875*0Sstevel@tonic-gate _token = '\b'; 876*0Sstevel@tonic-gate else if (*token == 'f') 877*0Sstevel@tonic-gate _token = '\f'; 878*0Sstevel@tonic-gate else if (*token == '\\') 879*0Sstevel@tonic-gate _token = '\\'; 880*0Sstevel@tonic-gate else if (*token == '"') 881*0Sstevel@tonic-gate _token = '"'; 882*0Sstevel@tonic-gate else if (*token == '\n') 883*0Sstevel@tonic-gate break; 884*0Sstevel@tonic-gate else 885*0Sstevel@tonic-gate _token = *token; 886*0Sstevel@tonic-gate 887*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1) && 888*0Sstevel@tonic-gate (fprintf(fdmsgs, "\\") < 0)) { 889*0Sstevel@tonic-gate (void) fprintf(stderr, 890*0Sstevel@tonic-gate Errmsg_wrte, flmsgs, 891*0Sstevel@tonic-gate strerror(errno)); 892*0Sstevel@tonic-gate return (1); 893*0Sstevel@tonic-gate } 894*0Sstevel@tonic-gate } else { 895*0Sstevel@tonic-gate /* 896*0Sstevel@tonic-gate * If this is the trailing quote then 897*0Sstevel@tonic-gate * thats the last of the message string. 898*0Sstevel@tonic-gate * Eat up any remaining white space and 899*0Sstevel@tonic-gate * unless an escape character is found 900*0Sstevel@tonic-gate * terminate the data string with a 0. 901*0Sstevel@tonic-gate */ 902*0Sstevel@tonic-gate if (*token == '"') { 903*0Sstevel@tonic-gate if (fdlint && (fprintf(fdlint, 904*0Sstevel@tonic-gate "%c", *token) < 0)) { 905*0Sstevel@tonic-gate (void) fprintf(stderr, 906*0Sstevel@tonic-gate Errmsg_wrte, fllint, 907*0Sstevel@tonic-gate strerror(errno)); 908*0Sstevel@tonic-gate return (1); 909*0Sstevel@tonic-gate } 910*0Sstevel@tonic-gate 911*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1) && 912*0Sstevel@tonic-gate (fprintf(fdmsgs, "%c", 913*0Sstevel@tonic-gate *token) < 0)) { 914*0Sstevel@tonic-gate (void) fprintf(stderr, 915*0Sstevel@tonic-gate Errmsg_wrte, flmsgs, 916*0Sstevel@tonic-gate strerror(errno)); 917*0Sstevel@tonic-gate return (1); 918*0Sstevel@tonic-gate } 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate while (*++token) { 921*0Sstevel@tonic-gate if (*token == '\n') 922*0Sstevel@tonic-gate break; 923*0Sstevel@tonic-gate } 924*0Sstevel@tonic-gate _token = '\0'; 925*0Sstevel@tonic-gate } else 926*0Sstevel@tonic-gate _token = *token; 927*0Sstevel@tonic-gate } 928*0Sstevel@tonic-gate 929*0Sstevel@tonic-gate if (fdmsgs && (prtmsgs == 1) && 930*0Sstevel@tonic-gate (fprintf(fdmsgs, "%c", *token) < 0)) { 931*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 932*0Sstevel@tonic-gate flmsgs, strerror(errno)); 933*0Sstevel@tonic-gate return (1); 934*0Sstevel@tonic-gate } 935*0Sstevel@tonic-gate 936*0Sstevel@tonic-gate if (fdlint && fprintf(fdlint, 937*0Sstevel@tonic-gate "%c", *token) < 0) { 938*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 939*0Sstevel@tonic-gate fllint, strerror(errno)); 940*0Sstevel@tonic-gate return (1); 941*0Sstevel@tonic-gate } 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate if (len >= bufsize) { 944*0Sstevel@tonic-gate bufsize += LINE_MAX; 945*0Sstevel@tonic-gate if ((token_buffer = realloc( 946*0Sstevel@tonic-gate token_buffer, bufsize)) == 0) { 947*0Sstevel@tonic-gate (void) fprintf(stderr, 948*0Sstevel@tonic-gate Errmsg_nmem, 949*0Sstevel@tonic-gate strerror(errno)); 950*0Sstevel@tonic-gate return (1); 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate } 953*0Sstevel@tonic-gate token_buffer[len] = _token; 954*0Sstevel@tonic-gate ptr++, token++, len++; 955*0Sstevel@tonic-gate escape = 0; 956*0Sstevel@tonic-gate 957*0Sstevel@tonic-gate if (_token == '\0') 958*0Sstevel@tonic-gate break; 959*0Sstevel@tonic-gate } 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate /* 962*0Sstevel@tonic-gate * After the complete message string has been processed 963*0Sstevel@tonic-gate * (including its continuation beyond one line), create 964*0Sstevel@tonic-gate * a string size definition. 965*0Sstevel@tonic-gate */ 966*0Sstevel@tonic-gate if (escape == 0) { 967*0Sstevel@tonic-gate const char *form = "#define\t%s_SIZE\t%d\n"; 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate token_buffer[len] = '\0'; 970*0Sstevel@tonic-gate 971*0Sstevel@tonic-gate message_append(defn, token_buffer); 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate if (fdlint && fprintf(fdlint, form, defn, 974*0Sstevel@tonic-gate (len - 1)) < 0) { 975*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, 976*0Sstevel@tonic-gate fllint, strerror(errno)); 977*0Sstevel@tonic-gate return (1); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate break; 981*0Sstevel@tonic-gate 982*0Sstevel@tonic-gate default: 983*0Sstevel@tonic-gate /* 984*0Sstevel@tonic-gate * Empty lines are passed through to the message file. 985*0Sstevel@tonic-gate */ 986*0Sstevel@tonic-gate while (isspace(*token)) 987*0Sstevel@tonic-gate token++; 988*0Sstevel@tonic-gate 989*0Sstevel@tonic-gate if (*token == 0) { 990*0Sstevel@tonic-gate if (msgid || (fdmsgs && (prtmsgs == 1))) { 991*0Sstevel@tonic-gate /* 992*0Sstevel@tonic-gate * If a msgid has been output a msgstr 993*0Sstevel@tonic-gate * must follow before we digest the new 994*0Sstevel@tonic-gate * token. 995*0Sstevel@tonic-gate */ 996*0Sstevel@tonic-gate if (msgid) { 997*0Sstevel@tonic-gate msgid = 0; 998*0Sstevel@tonic-gate str = "msgstr\t\"\"\n\n"; 999*0Sstevel@tonic-gate } else 1000*0Sstevel@tonic-gate str = "\n"; 1001*0Sstevel@tonic-gate 1002*0Sstevel@tonic-gate if (fprintf(fdmsgs, str) < 0) { 1003*0Sstevel@tonic-gate (void) fprintf(stderr, 1004*0Sstevel@tonic-gate Errmsg_wrte, flmsgs, 1005*0Sstevel@tonic-gate strerror(errno)); 1006*0Sstevel@tonic-gate return (1); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate break; 1010*0Sstevel@tonic-gate } 1011*0Sstevel@tonic-gate 1012*0Sstevel@tonic-gate /* 1013*0Sstevel@tonic-gate * If an escape is in effect then any tokens are taken 1014*0Sstevel@tonic-gate * to be message continuations. 1015*0Sstevel@tonic-gate */ 1016*0Sstevel@tonic-gate if (escape) { 1017*0Sstevel@tonic-gate escape = 0; 1018*0Sstevel@tonic-gate goto message; 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate (void) fprintf(stderr, "file %s: line %d: invalid " 1022*0Sstevel@tonic-gate "input does not start with #, $ or @\n", fldesc, 1023*0Sstevel@tonic-gate line); 1024*0Sstevel@tonic-gate return (1); 1025*0Sstevel@tonic-gate } 1026*0Sstevel@tonic-gate line++; 1027*0Sstevel@tonic-gate } 1028*0Sstevel@tonic-gate 1029*0Sstevel@tonic-gate free(token_buffer); 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate return (0); 1032*0Sstevel@tonic-gate } 1033*0Sstevel@tonic-gate 1034*0Sstevel@tonic-gate int 1035*0Sstevel@tonic-gate main(int argc, char ** argv) 1036*0Sstevel@tonic-gate { 1037*0Sstevel@tonic-gate opterr = 0; 1038*0Sstevel@tonic-gate while ((line = getopt(argc, argv, "cd:h:lm:n:i:v")) != EOF) { 1039*0Sstevel@tonic-gate switch (line) { 1040*0Sstevel@tonic-gate case 'c': /* catgets instead of gettext */ 1041*0Sstevel@tonic-gate cflag = 1; 1042*0Sstevel@tonic-gate break; 1043*0Sstevel@tonic-gate case 'd': /* new message data filename */ 1044*0Sstevel@tonic-gate fldata = optarg; /* (msg.c is default) */ 1045*0Sstevel@tonic-gate break; 1046*0Sstevel@tonic-gate case 'h': /* new message defs filename */ 1047*0Sstevel@tonic-gate fldefs = optarg; /* (msg.h is default) */ 1048*0Sstevel@tonic-gate break; 1049*0Sstevel@tonic-gate case 'i': /* input message ids from */ 1050*0Sstevel@tonic-gate flmids = optarg; /* from this file */ 1051*0Sstevel@tonic-gate break; 1052*0Sstevel@tonic-gate case 'l': /* define message data arrays */ 1053*0Sstevel@tonic-gate lflag = 1; /* to be local (static) */ 1054*0Sstevel@tonic-gate break; 1055*0Sstevel@tonic-gate case 'm': /* generate message database */ 1056*0Sstevel@tonic-gate flmsgs = optarg; /* to this file */ 1057*0Sstevel@tonic-gate break; 1058*0Sstevel@tonic-gate case 'n': /* new data array and func */ 1059*0Sstevel@tonic-gate interface = optarg; /* name (msg is default) */ 1060*0Sstevel@tonic-gate break; 1061*0Sstevel@tonic-gate case 'v': 1062*0Sstevel@tonic-gate vflag = 1; /* set verbose flag */ 1063*0Sstevel@tonic-gate break; 1064*0Sstevel@tonic-gate case '?': 1065*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_use, argv[0]); 1066*0Sstevel@tonic-gate exit(1); 1067*0Sstevel@tonic-gate default: 1068*0Sstevel@tonic-gate break; 1069*0Sstevel@tonic-gate } 1070*0Sstevel@tonic-gate } 1071*0Sstevel@tonic-gate 1072*0Sstevel@tonic-gate /* 1073*0Sstevel@tonic-gate * Validate the we have been given at least one input file. 1074*0Sstevel@tonic-gate */ 1075*0Sstevel@tonic-gate if ((argc - optind) < 1) { 1076*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_use); 1077*0Sstevel@tonic-gate exit(1); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate /* 1081*0Sstevel@tonic-gate * Open all the required output files. 1082*0Sstevel@tonic-gate */ 1083*0Sstevel@tonic-gate if (fldefs) { 1084*0Sstevel@tonic-gate if ((fddefs = fopen(fldefs, "w+")) == NULL) { 1085*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, fldefs, 1086*0Sstevel@tonic-gate strerror(errno)); 1087*0Sstevel@tonic-gate return (1); 1088*0Sstevel@tonic-gate } 1089*0Sstevel@tonic-gate } 1090*0Sstevel@tonic-gate if (fldata) { 1091*0Sstevel@tonic-gate if (fldefs && (strcmp(fldefs, fldata) == 0)) 1092*0Sstevel@tonic-gate fddata = fddefs; 1093*0Sstevel@tonic-gate else if ((fddata = fopen(fldata, "w+")) == NULL) { 1094*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, fldata, 1095*0Sstevel@tonic-gate strerror(errno)); 1096*0Sstevel@tonic-gate return (1); 1097*0Sstevel@tonic-gate } 1098*0Sstevel@tonic-gate } 1099*0Sstevel@tonic-gate if (fddefs && fddata) { 1100*0Sstevel@tonic-gate (void) sprintf(fllint, "%s.%d", nmlint, (int)getpid()); 1101*0Sstevel@tonic-gate if ((fdlint = fopen(fllint, "w+")) == NULL) { 1102*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, fllint, 1103*0Sstevel@tonic-gate strerror(errno)); 1104*0Sstevel@tonic-gate return (1); 1105*0Sstevel@tonic-gate } 1106*0Sstevel@tonic-gate } 1107*0Sstevel@tonic-gate if (flmsgs) { 1108*0Sstevel@tonic-gate if ((fdmsgs = fopen(flmsgs, "w+")) == NULL) { 1109*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, flmsgs, 1110*0Sstevel@tonic-gate strerror(errno)); 1111*0Sstevel@tonic-gate return (1); 1112*0Sstevel@tonic-gate } 1113*0Sstevel@tonic-gate } 1114*0Sstevel@tonic-gate if (flmids) { 1115*0Sstevel@tonic-gate if ((fdmids = fopen(flmids, "r")) == NULL) { 1116*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, flmids, 1117*0Sstevel@tonic-gate strerror(errno)); 1118*0Sstevel@tonic-gate return (1); 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate /* 1124*0Sstevel@tonic-gate * Initialize the message definition and message data streams. 1125*0Sstevel@tonic-gate */ 1126*0Sstevel@tonic-gate if (fddefs) { 1127*0Sstevel@tonic-gate if (init_defs()) 1128*0Sstevel@tonic-gate return (1); 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate /* 1132*0Sstevel@tonic-gate * Read the input message file, and for each line process accordingly. 1133*0Sstevel@tonic-gate */ 1134*0Sstevel@tonic-gate for (; optind < argc; optind++) { 1135*0Sstevel@tonic-gate int err; 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate fldesc = argv[optind]; 1138*0Sstevel@tonic-gate 1139*0Sstevel@tonic-gate if ((fddesc = fopen(fldesc, "r")) == NULL) { 1140*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_opne, fldesc, 1141*0Sstevel@tonic-gate strerror(errno)); 1142*0Sstevel@tonic-gate return (1); 1143*0Sstevel@tonic-gate } 1144*0Sstevel@tonic-gate err = file(); 1145*0Sstevel@tonic-gate (void) fclose(fddesc); 1146*0Sstevel@tonic-gate 1147*0Sstevel@tonic-gate if (err != 0) 1148*0Sstevel@tonic-gate return (1); 1149*0Sstevel@tonic-gate } 1150*0Sstevel@tonic-gate 1151*0Sstevel@tonic-gate /* 1152*0Sstevel@tonic-gate * If a msgid has been output a msgstr must follow before we end the 1153*0Sstevel@tonic-gate * file. 1154*0Sstevel@tonic-gate */ 1155*0Sstevel@tonic-gate if (msgid) { 1156*0Sstevel@tonic-gate msgid = 0; 1157*0Sstevel@tonic-gate if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) { 1158*0Sstevel@tonic-gate (void) fprintf(stderr, Errmsg_wrte, flmsgs, 1159*0Sstevel@tonic-gate strerror(errno)); 1160*0Sstevel@tonic-gate return (1); 1161*0Sstevel@tonic-gate } 1162*0Sstevel@tonic-gate } 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate if (fdmids) 1165*0Sstevel@tonic-gate (void) fclose(fdmids); 1166*0Sstevel@tonic-gate if (fdmsgs) 1167*0Sstevel@tonic-gate (void) fclose(fdmsgs); 1168*0Sstevel@tonic-gate 1169*0Sstevel@tonic-gate if (fddefs) { 1170*0Sstevel@tonic-gate if (output_defs()) 1171*0Sstevel@tonic-gate return (1); 1172*0Sstevel@tonic-gate } 1173*0Sstevel@tonic-gate 1174*0Sstevel@tonic-gate /* 1175*0Sstevel@tonic-gate * Finish off any generated data and header file. 1176*0Sstevel@tonic-gate */ 1177*0Sstevel@tonic-gate if (fldata) { 1178*0Sstevel@tonic-gate if (output_data()) 1179*0Sstevel@tonic-gate return (1); 1180*0Sstevel@tonic-gate } 1181*0Sstevel@tonic-gate if (fddefs) { 1182*0Sstevel@tonic-gate if (fini_defs()) 1183*0Sstevel@tonic-gate return (1); 1184*0Sstevel@tonic-gate } 1185*0Sstevel@tonic-gate 1186*0Sstevel@tonic-gate if (vflag) 1187*0Sstevel@tonic-gate dump_stringtab(stp); 1188*0Sstevel@tonic-gate 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate /* 1191*0Sstevel@tonic-gate * Close up everything and go home. 1192*0Sstevel@tonic-gate */ 1193*0Sstevel@tonic-gate if (fddata) 1194*0Sstevel@tonic-gate (void) fclose(fddata); 1195*0Sstevel@tonic-gate if (fddefs && (fddefs != fddata)) 1196*0Sstevel@tonic-gate (void) fclose(fddefs); 1197*0Sstevel@tonic-gate if (fddefs && fddata) { 1198*0Sstevel@tonic-gate (void) fclose(fdlint); 1199*0Sstevel@tonic-gate (void) unlink(fllint); 1200*0Sstevel@tonic-gate } 1201*0Sstevel@tonic-gate 1202*0Sstevel@tonic-gate if (stp) 1203*0Sstevel@tonic-gate st_destroy(stp); 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate return (0); 1206*0Sstevel@tonic-gate } 1207