xref: /illumos-gate/usr/src/tools/sgs/sgsmsg/sgsmsg.c (revision 4b9db4f6425b1a08fca4390f446072c4a6aae8d5)
169b1fd3fSRichard Lowe /*
269b1fd3fSRichard Lowe  * CDDL HEADER START
369b1fd3fSRichard Lowe  *
469b1fd3fSRichard Lowe  * The contents of this file are subject to the terms of the
569b1fd3fSRichard Lowe  * Common Development and Distribution License (the "License").
669b1fd3fSRichard Lowe  * You may not use this file except in compliance with the License.
769b1fd3fSRichard Lowe  *
869b1fd3fSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
969b1fd3fSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
1069b1fd3fSRichard Lowe  * See the License for the specific language governing permissions
1169b1fd3fSRichard Lowe  * and limitations under the License.
1269b1fd3fSRichard Lowe  *
1369b1fd3fSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
1469b1fd3fSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1569b1fd3fSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
1669b1fd3fSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
1769b1fd3fSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
1869b1fd3fSRichard Lowe  *
1969b1fd3fSRichard Lowe  * CDDL HEADER END
2069b1fd3fSRichard Lowe  */
2169b1fd3fSRichard Lowe /*
2269b1fd3fSRichard Lowe  * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
2369b1fd3fSRichard Lowe  *
2469b1fd3fSRichard Lowe  * sgsmsg generates several message files from an input template file.  Messages
25*4b9db4f6SChris Fraire  * are constructed for use with gettext(3C) - the default - or catgets(3C).  The
2669b1fd3fSRichard Lowe  * files generate are:
2769b1fd3fSRichard Lowe  *
2869b1fd3fSRichard Lowe  * msg.h	a header file containing definitions for each message.  The -h
2969b1fd3fSRichard Lowe  *		option triggers the creation of these definitions and specifies
3069b1fd3fSRichard Lowe  *		the name to use.
3169b1fd3fSRichard Lowe  *
3269b1fd3fSRichard Lowe  * msg.c	a data array of message strings.  The msg.h definitions are
3369b1fd3fSRichard Lowe  *		offsets into this array.  The -d option triggers the creation of
3469b1fd3fSRichard Lowe  *		these definitions and specifies the name to use.
3569b1fd3fSRichard Lowe  *
36*4b9db4f6SChris Fraire  * messages	a message file suitable for catgets(3C) or gettext(3C) use.  The
3769b1fd3fSRichard Lowe  *		-m option triggers this output and specifies the filename to be
3869b1fd3fSRichard Lowe  *		used.
3969b1fd3fSRichard Lowe  *
4069b1fd3fSRichard Lowe  * The template file is processed based on the first character of each line:
4169b1fd3fSRichard Lowe  *
4269b1fd3fSRichard Lowe  * # or $	entries are copied (as is) to the message file (messages).
4369b1fd3fSRichard Lowe  *
4469b1fd3fSRichard Lowe  * @ token(s)	entries are translated.  Two translations are possible dependent
4569b1fd3fSRichard Lowe  *		on whether one or more tokens are supplied:
4669b1fd3fSRichard Lowe  *
4769b1fd3fSRichard Lowe  *		A single token is interpreted as one of two reserved message
4869b1fd3fSRichard Lowe  *		output indicators, or a message identifier.  The reserved output
4969b1fd3fSRichard Lowe  *		indicator _START_ enables output to the message file - Note that
5069b1fd3fSRichard Lowe  *		the occurance of any other @ token will also enable message
5169b1fd3fSRichard Lowe  *		output.  The reserved output indicator _END_ disables output to
5269b1fd3fSRichard Lowe  *		the message file.  The use of these two indicators provides for
5369b1fd3fSRichard Lowe  *		only those message strings that require translation to be output
5469b1fd3fSRichard Lowe  *		to the message file.
5569b1fd3fSRichard Lowe  *
5669b1fd3fSRichard Lowe  *		Besides the reserved output indicators, a single token is taken
5769b1fd3fSRichard Lowe  *		to be a message identifier which will be subsituted for a
5869b1fd3fSRichard Lowe  *		`setid' for catgets(3c) output, or a `domain' name for
59*4b9db4f6SChris Fraire  *		gettext(3C) output.  This value is determine by substituting the
6069b1fd3fSRichard Lowe  *		token for the associated definition found in the message
6169b1fd3fSRichard Lowe  *		identifier file (specified with the -i option).
6269b1fd3fSRichard Lowe  *
6369b1fd3fSRichard Lowe  *		Multiple tokens are taken to be a message definition followed by
6469b1fd3fSRichard Lowe  *		the associated message string.  The message string is copied to
6569b1fd3fSRichard Lowe  *		the data array being built in msg.c.  The index into this array
6669b1fd3fSRichard Lowe  *		becomes the `message' identifier created in the msg.h file.
6769b1fd3fSRichard Lowe  */
6869b1fd3fSRichard Lowe 
6969b1fd3fSRichard Lowe #include	<fcntl.h>
7069b1fd3fSRichard Lowe #include	<stdlib.h>
7169b1fd3fSRichard Lowe #include	<stdio.h>
7269b1fd3fSRichard Lowe #include	<unistd.h>
7369b1fd3fSRichard Lowe #include	<limits.h>
7469b1fd3fSRichard Lowe #include	<string.h>
7569b1fd3fSRichard Lowe #include	<ctype.h>
7669b1fd3fSRichard Lowe #include	<errno.h>
7769b1fd3fSRichard Lowe #include	<sys/param.h>
7869b1fd3fSRichard Lowe 
7969b1fd3fSRichard Lowe #include	<sgs.h>
8069b1fd3fSRichard Lowe #include	<_string_table.h>
8169b1fd3fSRichard Lowe 
8269b1fd3fSRichard Lowe /*
8369b1fd3fSRichard Lowe  * Define any error message strings.
8469b1fd3fSRichard Lowe  */
8569b1fd3fSRichard Lowe static const char
8669b1fd3fSRichard Lowe 	* Errmsg_malt =	"sgsmsg: file %s: line %d: malformed input "
8769b1fd3fSRichard Lowe 			"at line\n",
8869b1fd3fSRichard Lowe 	* Errmsg_nmem =	"sgsmsg: memory allocation failed: %s\n",
8969b1fd3fSRichard Lowe 	* Errmsg_opne =	"sgsmsg: file %s: open failed: %s\n",
9069b1fd3fSRichard Lowe 	* Errmsg_wrte =	"sgsmsg: file %s: write failed: %s\n",
9169b1fd3fSRichard Lowe 	* Errmsg_read =	"sgsmsg: file %s: read failed %s\n",
9269b1fd3fSRichard Lowe 	* Errmsg_stnw =	"sgsmsg: st_new(): failed: %s\n",
9369b1fd3fSRichard Lowe 	* Errmsg_stin =	"sgsmsg: Str_tbl insert failed: %s\n",
9469b1fd3fSRichard Lowe 	* Errmsg_mnfn =	"sgsmsg: message not found in Str_tbl: %s\n",
9569b1fd3fSRichard Lowe 	* Errmsg_use  =	"usage: sgsmsg [-clv] [-d mesgdata] [-h mesgdefs] "
9669b1fd3fSRichard Lowe 			"[-m messages] [-n name] [-i mesgident] file ...\n";
9769b1fd3fSRichard Lowe 
9869b1fd3fSRichard Lowe /*
9969b1fd3fSRichard Lowe  * Define all output filenames and associated descriptors.
10069b1fd3fSRichard Lowe  */
10169b1fd3fSRichard Lowe static FILE	*fddefs, *fddata, *fdmsgs, *fdmids, *fddesc;
10269b1fd3fSRichard Lowe static char	*fldefs, *fldata, *flmsgs, *flmids, *fldesc;
10369b1fd3fSRichard Lowe static FILE	*fdlint;
10469b1fd3fSRichard Lowe static char	fllint[MAXPATHLEN];
10569b1fd3fSRichard Lowe 
10669b1fd3fSRichard Lowe static uint_t		vflag;	/* verbose flag */
10769b1fd3fSRichard Lowe static Str_tbl		*stp;	/* string table */
10869b1fd3fSRichard Lowe 
10969b1fd3fSRichard Lowe /*
11069b1fd3fSRichard Lowe  * Define any default strings.
11169b1fd3fSRichard Lowe  */
11269b1fd3fSRichard Lowe static const char
11369b1fd3fSRichard Lowe 	*nmlint =	"/tmp/sgsmsg.lint",
11469b1fd3fSRichard Lowe 	*interface =	"sgs_msg",
11569b1fd3fSRichard Lowe 	*start =	"_START_",
11669b1fd3fSRichard Lowe 	*end =		"_END_";
11769b1fd3fSRichard Lowe 
11869b1fd3fSRichard Lowe /*
11969b1fd3fSRichard Lowe  * Define any default flags and data items.
12069b1fd3fSRichard Lowe  */
12169b1fd3fSRichard Lowe static int	cflag = 0, lflag = 0, prtmsgs = 0, line, ptr = 1, msgid = 0;
12269b1fd3fSRichard Lowe static char	*mesgid = 0, *setid = 0, *domain = 0;
12369b1fd3fSRichard Lowe 
12469b1fd3fSRichard Lowe typedef struct msg_string {
12569b1fd3fSRichard Lowe 	char			*ms_defn;
12669b1fd3fSRichard Lowe 	char			*ms_message;
12769b1fd3fSRichard Lowe 	struct msg_string	*ms_next;
12869b1fd3fSRichard Lowe } msg_string;
12969b1fd3fSRichard Lowe 
13069b1fd3fSRichard Lowe static msg_string	*msg_head;
13169b1fd3fSRichard Lowe static msg_string	*msg_tail;
13269b1fd3fSRichard Lowe 
13369b1fd3fSRichard Lowe /*
13469b1fd3fSRichard Lowe  * message_append() is responsible for both inserting strings into
13569b1fd3fSRichard Lowe  * the master Str_tbl as well as maintaining a list of the
13669b1fd3fSRichard Lowe  * DEFINITIONS associated with each string.
13769b1fd3fSRichard Lowe  *
13869b1fd3fSRichard Lowe  * The list of strings is traversed at the end once the full
13969b1fd3fSRichard Lowe  * Str_tbl has been constructed - and string offsets can be
14069b1fd3fSRichard Lowe  * assigned.
14169b1fd3fSRichard Lowe  */
14269b1fd3fSRichard Lowe static void
message_append(const char * defn,const char * message)14369b1fd3fSRichard Lowe message_append(const char *defn, const char *message)
14469b1fd3fSRichard Lowe {
14569b1fd3fSRichard Lowe 	msg_string	*msg;
14669b1fd3fSRichard Lowe 	if ((msg = calloc(sizeof (msg_string), 1)) == 0) {
14769b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
14869b1fd3fSRichard Lowe 		exit(1);
14969b1fd3fSRichard Lowe 	}
15069b1fd3fSRichard Lowe 
15169b1fd3fSRichard Lowe 	/*
15269b1fd3fSRichard Lowe 	 * Initialize the string table.
15369b1fd3fSRichard Lowe 	 */
15469b1fd3fSRichard Lowe 	if ((stp == 0) && ((stp = st_new(FLG_STNEW_COMPRESS)) == NULL)) {
15569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_stnw, strerror(errno));
15669b1fd3fSRichard Lowe 		exit(1);
15769b1fd3fSRichard Lowe 	}
15869b1fd3fSRichard Lowe 
15969b1fd3fSRichard Lowe 
16069b1fd3fSRichard Lowe 	if ((msg->ms_defn = strdup(defn)) == 0) {
16169b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
16269b1fd3fSRichard Lowe 		exit(1);
16369b1fd3fSRichard Lowe 	}
16469b1fd3fSRichard Lowe 	if ((msg->ms_message = strdup(message)) == 0) {
16569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
16669b1fd3fSRichard Lowe 		exit(1);
16769b1fd3fSRichard Lowe 	}
16869b1fd3fSRichard Lowe 
16969b1fd3fSRichard Lowe 	if (st_insert(stp, msg->ms_message) == -1) {
17069b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_stin,
17169b1fd3fSRichard Lowe 		    message);
17269b1fd3fSRichard Lowe 		exit(1);
17369b1fd3fSRichard Lowe 	}
17469b1fd3fSRichard Lowe 
17569b1fd3fSRichard Lowe 	if (msg_head == 0) {
17669b1fd3fSRichard Lowe 		msg_head = msg_tail = msg;
17769b1fd3fSRichard Lowe 		return;
17869b1fd3fSRichard Lowe 	}
17969b1fd3fSRichard Lowe 	msg_tail->ms_next = msg;
18069b1fd3fSRichard Lowe 	msg_tail = msg;
18169b1fd3fSRichard Lowe }
18269b1fd3fSRichard Lowe 
18369b1fd3fSRichard Lowe /*
18469b1fd3fSRichard Lowe  * Initialize a setid value.  Given a setid definition determine its numeric
18569b1fd3fSRichard Lowe  * value from the specified message identifier file (specified with the -i
18669b1fd3fSRichard Lowe  * option).  Return a pointer to the numeric string.
18769b1fd3fSRichard Lowe  */
18869b1fd3fSRichard Lowe static int
getmesgid(char * id)18969b1fd3fSRichard Lowe getmesgid(char *id)
19069b1fd3fSRichard Lowe {
19169b1fd3fSRichard Lowe 	char	*buffer, *token, *_mesgid = 0, *_setid = 0, *_domain = 0;
19269b1fd3fSRichard Lowe 
19369b1fd3fSRichard Lowe 	/*
19469b1fd3fSRichard Lowe 	 * If we're being asked to interpret a message id but the user didn't
19569b1fd3fSRichard Lowe 	 * provide the required message identifier file (-i option) we're in
19669b1fd3fSRichard Lowe 	 * trouble.
19769b1fd3fSRichard Lowe 	 */
19869b1fd3fSRichard Lowe 	if (flmids == 0) {
19969b1fd3fSRichard Lowe 		(void) fprintf(stderr, "sgsmsg: file %s: line %d: mesgid %s: "
20069b1fd3fSRichard Lowe 		    "unable to process mesgid\n\t"
20169b1fd3fSRichard Lowe 		    "no message identifier file specified "
20269b1fd3fSRichard Lowe 		    "(see -i option)\n", fldesc, line, id);
20369b1fd3fSRichard Lowe 		return (1);
20469b1fd3fSRichard Lowe 	}
20569b1fd3fSRichard Lowe 
20669b1fd3fSRichard Lowe 	if ((buffer = malloc(LINE_MAX)) == 0) {
20769b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
20869b1fd3fSRichard Lowe 		return (1);
20969b1fd3fSRichard Lowe 	}
21069b1fd3fSRichard Lowe 
21169b1fd3fSRichard Lowe 	/*
21269b1fd3fSRichard Lowe 	 * Read the message identifier file and locate the required mesgid.
21369b1fd3fSRichard Lowe 	 */
21469b1fd3fSRichard Lowe 	rewind(fdmids);
21569b1fd3fSRichard Lowe 	while (fgets(buffer, LINE_MAX, fdmids) != NULL) {
21669b1fd3fSRichard Lowe 		if ((token = strstr(buffer, id)) == NULL)
21769b1fd3fSRichard Lowe 			continue;
21869b1fd3fSRichard Lowe 
21969b1fd3fSRichard Lowe 		/*
22069b1fd3fSRichard Lowe 		 * Establish individual strings for the mesgid, setid and domain
22169b1fd3fSRichard Lowe 		 * values.
22269b1fd3fSRichard Lowe 		 */
22369b1fd3fSRichard Lowe 		_mesgid = token;
22469b1fd3fSRichard Lowe 		while (!(isspace(*token)))
22569b1fd3fSRichard Lowe 			token++;
22669b1fd3fSRichard Lowe 		*token++ = 0;
22769b1fd3fSRichard Lowe 
22869b1fd3fSRichard Lowe 		while (isspace(*token))
22969b1fd3fSRichard Lowe 			token++;
23069b1fd3fSRichard Lowe 		_setid = token;
23169b1fd3fSRichard Lowe 		while (!(isspace(*token)))
23269b1fd3fSRichard Lowe 			token++;
23369b1fd3fSRichard Lowe 		*token++ = 0;
23469b1fd3fSRichard Lowe 
23569b1fd3fSRichard Lowe 		while (isspace(*token))
23669b1fd3fSRichard Lowe 			token++;
23769b1fd3fSRichard Lowe 		_domain = token;
23869b1fd3fSRichard Lowe 		while (!(isspace(*token)))
23969b1fd3fSRichard Lowe 			token++;
24069b1fd3fSRichard Lowe 		*token = 0;
24169b1fd3fSRichard Lowe 		break;
24269b1fd3fSRichard Lowe 	}
24369b1fd3fSRichard Lowe 
24469b1fd3fSRichard Lowe 	/*
24569b1fd3fSRichard Lowe 	 * Did we find a match?
24669b1fd3fSRichard Lowe 	 */
24769b1fd3fSRichard Lowe 	if ((_mesgid == 0) || (_setid == 0) || (_domain == 0)) {
24869b1fd3fSRichard Lowe 		(void) fprintf(stderr, "sgsmsg: file %s: line %d: mesgid %s: "
24969b1fd3fSRichard Lowe 		    "unable to process mesgid\n\t"
25069b1fd3fSRichard Lowe 		    "identifier does not exist in file %s\n",
25169b1fd3fSRichard Lowe 		    fldesc, line, id, flmids);
25269b1fd3fSRichard Lowe 		return (1);
25369b1fd3fSRichard Lowe 	}
25469b1fd3fSRichard Lowe 
25569b1fd3fSRichard Lowe 	/*
25669b1fd3fSRichard Lowe 	 * Have we been here before?
25769b1fd3fSRichard Lowe 	 */
25869b1fd3fSRichard Lowe 	if (mesgid) {
25969b1fd3fSRichard Lowe 		if (cflag == 1) {
26069b1fd3fSRichard Lowe 			/*
26169b1fd3fSRichard Lowe 			 * If we're being asked to process more than one mesgid
26269b1fd3fSRichard Lowe 			 * warn the user that only one mesgid can be used for
26369b1fd3fSRichard Lowe 			 * the catgets(3c) call.
26469b1fd3fSRichard Lowe 			 */
26569b1fd3fSRichard Lowe 			(void) fprintf(stderr, "sgsmsg: file %s: line %d: "
26669b1fd3fSRichard Lowe 			    "setid %s: warning: multiple mesgids "
26769b1fd3fSRichard Lowe 			    "encountered\n\t"
26869b1fd3fSRichard Lowe 			    "last setting used in messaging code\n",
26969b1fd3fSRichard Lowe 			    fldesc, line, id);
27069b1fd3fSRichard Lowe 		}
27169b1fd3fSRichard Lowe 	}
27269b1fd3fSRichard Lowe 
27369b1fd3fSRichard Lowe 	mesgid = _mesgid;
27469b1fd3fSRichard Lowe 	setid = _setid;
27569b1fd3fSRichard Lowe 	domain = _domain;
27669b1fd3fSRichard Lowe 
27769b1fd3fSRichard Lowe 	/*
27869b1fd3fSRichard Lowe 	 * Generate the message file output (insure output flag is enabled).
27969b1fd3fSRichard Lowe 	 */
28069b1fd3fSRichard Lowe 	if (prtmsgs != -1)
28169b1fd3fSRichard Lowe 		prtmsgs = 1;
28269b1fd3fSRichard Lowe 	if (fdmsgs && (prtmsgs == 1)) {
28369b1fd3fSRichard Lowe 		if (cflag == 1) {
28469b1fd3fSRichard Lowe 			if (fprintf(fdmsgs, "$quote \"\n$set %s\n",
28569b1fd3fSRichard Lowe 			    setid) < 0) {
28669b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_wrte, flmsgs,
28769b1fd3fSRichard Lowe 				    strerror(errno));
28869b1fd3fSRichard Lowe 				return (1);
28969b1fd3fSRichard Lowe 			}
29069b1fd3fSRichard Lowe 		} else {
29169b1fd3fSRichard Lowe 			if (fprintf(fdmsgs, "domain\t\"%s\"\n", domain) < 0) {
29269b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_wrte, flmsgs,
29369b1fd3fSRichard Lowe 				    strerror(errno));
29469b1fd3fSRichard Lowe 				return (1);
29569b1fd3fSRichard Lowe 			}
29669b1fd3fSRichard Lowe 		}
29769b1fd3fSRichard Lowe 	}
29869b1fd3fSRichard Lowe 
29969b1fd3fSRichard Lowe 	/*
30069b1fd3fSRichard Lowe 	 * For catgets(3c) output generate a setid definition in the message
30169b1fd3fSRichard Lowe 	 * definition file.
30269b1fd3fSRichard Lowe 	 */
30369b1fd3fSRichard Lowe 	if (fddefs && (cflag == 1) &&
30469b1fd3fSRichard Lowe 	    (fprintf(fddefs, "#define\t%s\t%s\n\n", mesgid, setid) < 0)) {
30569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
30669b1fd3fSRichard Lowe 		return (1);
30769b1fd3fSRichard Lowe 	}
30869b1fd3fSRichard Lowe 
30969b1fd3fSRichard Lowe 	return (0);
31069b1fd3fSRichard Lowe }
31169b1fd3fSRichard Lowe 
31269b1fd3fSRichard Lowe /*
31369b1fd3fSRichard Lowe  * Dump contents of String Table to standard out
31469b1fd3fSRichard Lowe  */
31569b1fd3fSRichard Lowe static void
dump_stringtab(Str_tbl * stp)31669b1fd3fSRichard Lowe dump_stringtab(Str_tbl *stp)
31769b1fd3fSRichard Lowe {
31869b1fd3fSRichard Lowe 	uint_t	cnt;
31969b1fd3fSRichard Lowe 
32069b1fd3fSRichard Lowe 	if ((stp->st_flags & FLG_STTAB_COMPRESS) == 0) {
32169b1fd3fSRichard Lowe 		(void) printf("string table full size: %ld: uncompressed\n",
32269b1fd3fSRichard Lowe 		    stp->st_fullstrsize);
32369b1fd3fSRichard Lowe 		return;
32469b1fd3fSRichard Lowe 	}
32569b1fd3fSRichard Lowe 
32669b1fd3fSRichard Lowe 	(void) printf("string table full size: %ld compressed down to: %ld\n\n",
32769b1fd3fSRichard Lowe 	    stp->st_fullstrsize, stp->st_strsize);
32869b1fd3fSRichard Lowe 	(void) printf("string table compression information [%d buckets]:\n",
32969b1fd3fSRichard Lowe 	    stp->st_hbckcnt);
33069b1fd3fSRichard Lowe 
33169b1fd3fSRichard Lowe 	for (cnt = 0; cnt < stp->st_hbckcnt; cnt++) {
33269b1fd3fSRichard Lowe 		Str_hash	*sthash = stp->st_hashbcks[cnt];
33369b1fd3fSRichard Lowe 
33469b1fd3fSRichard Lowe 		if (sthash == 0)
33569b1fd3fSRichard Lowe 			continue;
33669b1fd3fSRichard Lowe 
33769b1fd3fSRichard Lowe 		(void) printf(" bucket: [%d]\n", cnt);
33869b1fd3fSRichard Lowe 
33969b1fd3fSRichard Lowe 		while (sthash) {
34069b1fd3fSRichard Lowe 			size_t	stroff = sthash->hi_mstr->sm_strlen -
34169b1fd3fSRichard Lowe 			    sthash->hi_strlen;
34269b1fd3fSRichard Lowe 
34369b1fd3fSRichard Lowe 			if (stroff == 0) {
34469b1fd3fSRichard Lowe 				(void) printf("  [%ld]: '%s'  <master>\n",
34569b1fd3fSRichard Lowe 				    sthash->hi_refcnt, sthash->hi_mstr->sm_str);
34669b1fd3fSRichard Lowe 			} else {
34769b1fd3fSRichard Lowe 				(void) printf("  [%ld]: '%s'  <suffix of: "
34869b1fd3fSRichard Lowe 				    "'%s'>\n", sthash->hi_refcnt,
34969b1fd3fSRichard Lowe 				    &sthash->hi_mstr->sm_str[stroff],
35069b1fd3fSRichard Lowe 				    sthash->hi_mstr->sm_str);
35169b1fd3fSRichard Lowe 			}
35269b1fd3fSRichard Lowe 			sthash = sthash->hi_next;
35369b1fd3fSRichard Lowe 		}
35469b1fd3fSRichard Lowe 	}
35569b1fd3fSRichard Lowe }
35669b1fd3fSRichard Lowe 
35769b1fd3fSRichard Lowe /*
35869b1fd3fSRichard Lowe  * Initialize the message definition header file stream.
35969b1fd3fSRichard Lowe  */
36069b1fd3fSRichard Lowe static int
init_defs(void)36169b1fd3fSRichard Lowe init_defs(void)
36269b1fd3fSRichard Lowe {
36369b1fd3fSRichard Lowe 	static char	guard[FILENAME_MAX + 6];
36469b1fd3fSRichard Lowe 	char		*optr;
36569b1fd3fSRichard Lowe 	const char	*iptr, *_ptr;
36669b1fd3fSRichard Lowe 
36769b1fd3fSRichard Lowe 	/*
36869b1fd3fSRichard Lowe 	 * Establish a header guard name using the files basename.
36969b1fd3fSRichard Lowe 	 */
37069b1fd3fSRichard Lowe 	for (iptr = 0, _ptr = fldefs; _ptr && (*_ptr != '\0'); _ptr++) {
37169b1fd3fSRichard Lowe 		if (*_ptr == '/')
37269b1fd3fSRichard Lowe 			iptr = _ptr + 1;
37369b1fd3fSRichard Lowe 	}
37469b1fd3fSRichard Lowe 	if (iptr == 0)
37569b1fd3fSRichard Lowe 		iptr = fldefs;
37669b1fd3fSRichard Lowe 
37769b1fd3fSRichard Lowe 	optr = guard;
37869b1fd3fSRichard Lowe 	for (*optr++ = '_'; iptr && (*iptr != '\0'); iptr++, optr++) {
37969b1fd3fSRichard Lowe 		if (*iptr == '.') {
38069b1fd3fSRichard Lowe 			*optr++ = '_';
38169b1fd3fSRichard Lowe 			*optr++ = 'D';
38269b1fd3fSRichard Lowe 			*optr++ = 'O';
38369b1fd3fSRichard Lowe 			*optr++ = 'T';
38469b1fd3fSRichard Lowe 			*optr = '_';
38569b1fd3fSRichard Lowe 		} else
38669b1fd3fSRichard Lowe 			*optr = toupper(*iptr);
38769b1fd3fSRichard Lowe 	}
38869b1fd3fSRichard Lowe 
38969b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#ifndef\t%s\n#define\t%s\n\n", guard, guard) < 0) {
39069b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
39169b1fd3fSRichard Lowe 		return (1);
39269b1fd3fSRichard Lowe 	}
39369b1fd3fSRichard Lowe 
39469b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#include <sgsmsg.h>\t/* Msg typedef */\n\n") < 0) {
39569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
39669b1fd3fSRichard Lowe 		return (1);
39769b1fd3fSRichard Lowe 	}
39869b1fd3fSRichard Lowe 
39969b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#ifndef\t__lint\n\n") < 0) {
40069b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
40169b1fd3fSRichard Lowe 		return (1);
40269b1fd3fSRichard Lowe 	}
40369b1fd3fSRichard Lowe 
40469b1fd3fSRichard Lowe 	/*
40569b1fd3fSRichard Lowe 	 * The MSG_SGS_ARRAY_NAME macro supplies a generic way to
40669b1fd3fSRichard Lowe 	 * reference the string table regardless of its name.
40769b1fd3fSRichard Lowe 	 */
40869b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#define\tMSG_SGS_LOCAL_ARRAY\t__%s\n\n",
40969b1fd3fSRichard Lowe 	    interface) < 0) {
41069b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
41169b1fd3fSRichard Lowe 		return (1);
41269b1fd3fSRichard Lowe 	}
41369b1fd3fSRichard Lowe 
41469b1fd3fSRichard Lowe 	/*
41569b1fd3fSRichard Lowe 	 * If the associated data array is global define a prototype.
41669b1fd3fSRichard Lowe 	 * Define a macro to access the array elements.
41769b1fd3fSRichard Lowe 	 */
41869b1fd3fSRichard Lowe 	if (lflag == 0) {
41969b1fd3fSRichard Lowe 		if (fprintf(fddefs, "extern\tconst char\t__%s[];\n\n",
42069b1fd3fSRichard Lowe 		    interface) < 0) {
42169b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte, fldefs,
42269b1fd3fSRichard Lowe 			    strerror(errno));
42369b1fd3fSRichard Lowe 			return (1);
42469b1fd3fSRichard Lowe 		}
42569b1fd3fSRichard Lowe 	}
42669b1fd3fSRichard Lowe 	if (fprintf(fddefs,
42769b1fd3fSRichard Lowe 	    "#define\tMSG_ORIG_STRTAB(_x, _s)\t&_s[_x]\n\n") < 0) {
42869b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
42969b1fd3fSRichard Lowe 		return (1);
43069b1fd3fSRichard Lowe 	}
43169b1fd3fSRichard Lowe 	if (fprintf(fddefs,
43269b1fd3fSRichard Lowe 	    "#define\tMSG_ORIG(x)\tMSG_ORIG_STRTAB(x, __%s)\n\n",
43369b1fd3fSRichard Lowe 	    interface) < 0) {
43469b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
43569b1fd3fSRichard Lowe 		return (1);
43669b1fd3fSRichard Lowe 	}
43769b1fd3fSRichard Lowe 
43869b1fd3fSRichard Lowe 	/*
43969b1fd3fSRichard Lowe 	 * Generate a prototype to access the associated data array.
44069b1fd3fSRichard Lowe 	 */
44169b1fd3fSRichard Lowe 	if (fprintf(fddefs, "extern\tconst char *\t_%s(Msg);\n\n",
44269b1fd3fSRichard Lowe 	    interface) < 0) {
44369b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
44469b1fd3fSRichard Lowe 		return (1);
44569b1fd3fSRichard Lowe 	}
44669b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#define\tMSG_INTL(x)\t_%s(x)\n\n",
44769b1fd3fSRichard Lowe 	    interface) < 0) {
44869b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
44969b1fd3fSRichard Lowe 		return (1);
45069b1fd3fSRichard Lowe 	}
45169b1fd3fSRichard Lowe 
45269b1fd3fSRichard Lowe 	return (0);
45369b1fd3fSRichard Lowe }
45469b1fd3fSRichard Lowe 
45569b1fd3fSRichard Lowe 
45669b1fd3fSRichard Lowe /*
45769b1fd3fSRichard Lowe  * Finish the message definition header file.
45869b1fd3fSRichard Lowe  */
45969b1fd3fSRichard Lowe static int
fini_defs(void)46069b1fd3fSRichard Lowe fini_defs(void)
46169b1fd3fSRichard Lowe {
46269b1fd3fSRichard Lowe 	if (fprintf(fddefs, "\n#else\t/* __lint */\n\n") < 0) {
46369b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
46469b1fd3fSRichard Lowe 		return (1);
46569b1fd3fSRichard Lowe 	}
46669b1fd3fSRichard Lowe 
46769b1fd3fSRichard Lowe 	if (fprintf(fddefs, "extern\tconst char *\t_%s(Msg);\n\n",
46869b1fd3fSRichard Lowe 	    interface) < 0) {
46969b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
47069b1fd3fSRichard Lowe 		return (1);
47169b1fd3fSRichard Lowe 	}
47269b1fd3fSRichard Lowe 
47369b1fd3fSRichard Lowe 	if (fprintf(fddefs, "#ifndef MSG_SGS_LOCAL_ARRAY\n"
47469b1fd3fSRichard Lowe 	    "#define\tMSG_SGS_LOCAL_ARRAY\t\"\"\n#endif\n\n") < 0) {
47569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
47669b1fd3fSRichard Lowe 		return (1);
47769b1fd3fSRichard Lowe 	}
47869b1fd3fSRichard Lowe 
47969b1fd3fSRichard Lowe 	if (lflag == 0) {
48069b1fd3fSRichard Lowe 		if (fprintf(fddefs, "extern\tconst char\t__%s[];\n\n",
48169b1fd3fSRichard Lowe 		    interface) < 0) {
48269b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte, fldefs,
48369b1fd3fSRichard Lowe 			    strerror(errno));
48469b1fd3fSRichard Lowe 			return (1);
48569b1fd3fSRichard Lowe 		}
48669b1fd3fSRichard Lowe 	}
48769b1fd3fSRichard Lowe 
48869b1fd3fSRichard Lowe 	if (fprintf(fddefs,
48969b1fd3fSRichard Lowe 	    "#define MSG_ORIG_STRTAB(_x, _s)\t_x\n"
49069b1fd3fSRichard Lowe 	    "#define MSG_ORIG(x)\tx\n#define MSG_INTL(x)\tx\n") < 0) {
49169b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
49269b1fd3fSRichard Lowe 		return (1);
49369b1fd3fSRichard Lowe 	}
49469b1fd3fSRichard Lowe 
49569b1fd3fSRichard Lowe 	/*
49669b1fd3fSRichard Lowe 	 * Provide a way to get the array and function declarations above
49769b1fd3fSRichard Lowe 	 * without also getting the actual messages. This is useful in
49869b1fd3fSRichard Lowe 	 * our lintsup.c files that include more than one message header.
49969b1fd3fSRichard Lowe 	 * lintsup doesn't need the actual messages, and this prevents
50069b1fd3fSRichard Lowe 	 * macro name collisions.
50169b1fd3fSRichard Lowe 	 */
50269b1fd3fSRichard Lowe 	if (fprintf(fddefs, "\n#ifndef LINTSUP_SUPPRESS_STRINGS\n") < 0) {
50369b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
50469b1fd3fSRichard Lowe 		return (1);
50569b1fd3fSRichard Lowe 	}
50669b1fd3fSRichard Lowe 
50769b1fd3fSRichard Lowe 	/*
50869b1fd3fSRichard Lowe 	 * Copy the temporary lint defs file into the new header.
50969b1fd3fSRichard Lowe 	 */
51069b1fd3fSRichard Lowe 	if (fdlint) {
51169b1fd3fSRichard Lowe 		long	size;
51269b1fd3fSRichard Lowe 		char	*buf;
51369b1fd3fSRichard Lowe 
51469b1fd3fSRichard Lowe 		size = ftell(fdlint);
51569b1fd3fSRichard Lowe 		(void) rewind(fdlint);
51669b1fd3fSRichard Lowe 
51769b1fd3fSRichard Lowe 		if ((buf = malloc(size)) == 0) {
51869b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
51969b1fd3fSRichard Lowe 			return (1);
52069b1fd3fSRichard Lowe 		}
52169b1fd3fSRichard Lowe 		if (fread(buf, size, 1, fdlint) == 0) {
52269b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_read, fllint,
52369b1fd3fSRichard Lowe 			    strerror(errno));
52469b1fd3fSRichard Lowe 			return (1);
52569b1fd3fSRichard Lowe 		}
52669b1fd3fSRichard Lowe 		if (fwrite(buf, size, 1, fddefs) == 0) {
52769b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte, fldefs,
52869b1fd3fSRichard Lowe 			    strerror(errno));
52969b1fd3fSRichard Lowe 			return (1);
53069b1fd3fSRichard Lowe 		}
53169b1fd3fSRichard Lowe 		(void) free(buf);
53269b1fd3fSRichard Lowe 	}
53369b1fd3fSRichard Lowe 
53469b1fd3fSRichard Lowe 	if (fprintf(fddefs, "\n#endif\t/* LINTSUP_SUPPRESS_STRINGS */\n") < 0) {
53569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
53669b1fd3fSRichard Lowe 		return (1);
53769b1fd3fSRichard Lowe 	}
53869b1fd3fSRichard Lowe 
53969b1fd3fSRichard Lowe 	if (fprintf(fddefs, "\n#endif\t/* __lint */\n") < 0) {
54069b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
54169b1fd3fSRichard Lowe 		return (1);
54269b1fd3fSRichard Lowe 	}
54369b1fd3fSRichard Lowe 
54469b1fd3fSRichard Lowe 	if (fprintf(fddefs, "\n#endif\n") < 0) {
54569b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldefs, strerror(errno));
54669b1fd3fSRichard Lowe 		return (1);
54769b1fd3fSRichard Lowe 	}
54869b1fd3fSRichard Lowe 
54969b1fd3fSRichard Lowe 	return (0);
55069b1fd3fSRichard Lowe }
55169b1fd3fSRichard Lowe 
55269b1fd3fSRichard Lowe /*
55369b1fd3fSRichard Lowe  * The entire messaging file has been scanned - and all strings have been
55469b1fd3fSRichard Lowe  * inserted into the string_table.  We can now walk the message queue
55569b1fd3fSRichard Lowe  * and create the '#define <DEFN>' for each string - with the strings
55669b1fd3fSRichard Lowe  * assigned offset into the string_table.
55769b1fd3fSRichard Lowe  */
55869b1fd3fSRichard Lowe static int
output_defs(void)55969b1fd3fSRichard Lowe output_defs(void)
56069b1fd3fSRichard Lowe {
56169b1fd3fSRichard Lowe 	msg_string	*msg;
56269b1fd3fSRichard Lowe 	size_t		stbufsize;
56369b1fd3fSRichard Lowe 	char		*stbuf;
56469b1fd3fSRichard Lowe 
56569b1fd3fSRichard Lowe 	stbufsize = st_getstrtab_sz(stp);
56669b1fd3fSRichard Lowe 	if ((stbuf = malloc(stbufsize)) == 0) {
56769b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
56869b1fd3fSRichard Lowe 		exit(1);
56969b1fd3fSRichard Lowe 	}
57069b1fd3fSRichard Lowe 	(void) st_setstrbuf(stp, stbuf, stbufsize);
57169b1fd3fSRichard Lowe 	for (msg = msg_head; msg; msg = msg->ms_next) {
57269b1fd3fSRichard Lowe 		size_t	stoff;
57369b1fd3fSRichard Lowe 		if ((st_setstring(stp, msg->ms_message, &stoff)) == -1) {
57469b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_mnfn, msg->ms_message);
57569b1fd3fSRichard Lowe 			return (1);
57669b1fd3fSRichard Lowe 		}
57769b1fd3fSRichard Lowe 		if (fprintf(fddefs, "\n#define\t%s\t%ld\n",
57869b1fd3fSRichard Lowe 		    msg->ms_defn, stoff) < 0) {
57969b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte,
58069b1fd3fSRichard Lowe 			    fldefs, strerror(errno));
58169b1fd3fSRichard Lowe 			return (1);
58269b1fd3fSRichard Lowe 		}
58369b1fd3fSRichard Lowe 		if (fddefs && fprintf(fddefs, "#define\t%s_SIZE\t%d\n",
58469b1fd3fSRichard Lowe 		    msg->ms_defn, strlen(msg->ms_message)) < 0) {
58569b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte,
58669b1fd3fSRichard Lowe 			    fldefs, strerror(errno));
58769b1fd3fSRichard Lowe 			return (1);
58869b1fd3fSRichard Lowe 		}
58969b1fd3fSRichard Lowe 	}
59069b1fd3fSRichard Lowe 	return (0);
59169b1fd3fSRichard Lowe }
59269b1fd3fSRichard Lowe 
59369b1fd3fSRichard Lowe 
59469b1fd3fSRichard Lowe /*
59569b1fd3fSRichard Lowe  * Finish off the data structure definition.
59669b1fd3fSRichard Lowe  */
59769b1fd3fSRichard Lowe static int
output_data(void)59869b1fd3fSRichard Lowe output_data(void)
59969b1fd3fSRichard Lowe {
60069b1fd3fSRichard Lowe 	size_t		stbufsize;
60169b1fd3fSRichard Lowe 	size_t		ndx;
60269b1fd3fSRichard Lowe 	size_t		column = 1;
60369b1fd3fSRichard Lowe 	const char	*stbuf;
60469b1fd3fSRichard Lowe 	const char	*fmtstr;
60569b1fd3fSRichard Lowe 
60669b1fd3fSRichard Lowe 	stbufsize = st_getstrtab_sz(stp);
60769b1fd3fSRichard Lowe 	stbuf = st_getstrbuf(stp);
60869b1fd3fSRichard Lowe 
60969b1fd3fSRichard Lowe 	assert(stbuf);
61069b1fd3fSRichard Lowe 
61169b1fd3fSRichard Lowe 	/*
61269b1fd3fSRichard Lowe 	 * Determine from the local flag whether the data declaration should
61369b1fd3fSRichard Lowe 	 * be static.
61469b1fd3fSRichard Lowe 	 */
61569b1fd3fSRichard Lowe 	if (lflag)
61669b1fd3fSRichard Lowe 		fmtstr = (const char *)"static const";
61769b1fd3fSRichard Lowe 	else
61869b1fd3fSRichard Lowe 		fmtstr = (const char *)"const";
61969b1fd3fSRichard Lowe 
62069b1fd3fSRichard Lowe 	if (fprintf(fddata, "\n%s char __%s[%ld] __attribute__((unused)) = { ",
62169b1fd3fSRichard Lowe 	    fmtstr, interface, stbufsize) < 0) {
62269b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldata, strerror(errno));
62369b1fd3fSRichard Lowe 		return (1);
62469b1fd3fSRichard Lowe 	}
62569b1fd3fSRichard Lowe 
62669b1fd3fSRichard Lowe 	for (ndx = 0; ndx < (stbufsize - 1); ndx++) {
62769b1fd3fSRichard Lowe 		if (column == 1) {
62869b1fd3fSRichard Lowe 			if (fddata && fprintf(fddata,
62969b1fd3fSRichard Lowe 			    "\n/* %4ld */ 0x%.2x,", ndx,
63069b1fd3fSRichard Lowe 			    (unsigned char)stbuf[ndx]) < 0) {
63169b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_wrte,
63269b1fd3fSRichard Lowe 				    fldata, strerror(errno));
63369b1fd3fSRichard Lowe 				return (1);
63469b1fd3fSRichard Lowe 			}
63569b1fd3fSRichard Lowe 		} else {
63669b1fd3fSRichard Lowe 			if (fddata && fprintf(fddata, "  0x%.2x,",
63769b1fd3fSRichard Lowe 			    (unsigned char)stbuf[ndx]) < 0) {
63869b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_wrte,
63969b1fd3fSRichard Lowe 				    fldata, strerror(errno));
64069b1fd3fSRichard Lowe 				return (1);
64169b1fd3fSRichard Lowe 			}
64269b1fd3fSRichard Lowe 		}
64369b1fd3fSRichard Lowe 
64469b1fd3fSRichard Lowe 		if (column++ == 10)
64569b1fd3fSRichard Lowe 			column = 1;
64669b1fd3fSRichard Lowe 	}
64769b1fd3fSRichard Lowe 
64869b1fd3fSRichard Lowe 	if (column == 1)
64969b1fd3fSRichard Lowe 		fmtstr = "\n\t0x%.2x };\n";
65069b1fd3fSRichard Lowe 	else
65169b1fd3fSRichard Lowe 		fmtstr = "  0x%.2x };\n";
65269b1fd3fSRichard Lowe 
65369b1fd3fSRichard Lowe 	if (fprintf(fddata, fmtstr, (unsigned char)stbuf[stbufsize - 1]) < 0) {
65469b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_wrte, fldata, strerror(errno));
65569b1fd3fSRichard Lowe 		return (1);
65669b1fd3fSRichard Lowe 	}
65769b1fd3fSRichard Lowe 
65869b1fd3fSRichard Lowe 	return (0);
65969b1fd3fSRichard Lowe }
66069b1fd3fSRichard Lowe 
66169b1fd3fSRichard Lowe static int
file()66269b1fd3fSRichard Lowe file()
66369b1fd3fSRichard Lowe {
66469b1fd3fSRichard Lowe 	char	buffer[LINE_MAX], * token;
66569b1fd3fSRichard Lowe 	uint_t	bufsize;
66669b1fd3fSRichard Lowe 	char	*token_buffer;
66769b1fd3fSRichard Lowe 	int	escape = 0;
66869b1fd3fSRichard Lowe 	int	len = 0;
66969b1fd3fSRichard Lowe 
67069b1fd3fSRichard Lowe 	if ((token_buffer = malloc(LINE_MAX)) == 0) {
67169b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_nmem, strerror(errno));
67269b1fd3fSRichard Lowe 		return (1);
67369b1fd3fSRichard Lowe 	}
67469b1fd3fSRichard Lowe 	bufsize = LINE_MAX;
67569b1fd3fSRichard Lowe 
67669b1fd3fSRichard Lowe 	line = 1;
67769b1fd3fSRichard Lowe 
67869b1fd3fSRichard Lowe 	while ((token = fgets(buffer, LINE_MAX, fddesc)) != NULL) {
67969b1fd3fSRichard Lowe 		char	defn[PATH_MAX], * _defn, * str;
68069b1fd3fSRichard Lowe 
68169b1fd3fSRichard Lowe 		switch (*token) {
68269b1fd3fSRichard Lowe 		case '#':
68369b1fd3fSRichard Lowe 		case '$':
68469b1fd3fSRichard Lowe 			if (escape) {
68569b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_malt, fldesc,
68669b1fd3fSRichard Lowe 				    line);
68769b1fd3fSRichard Lowe 				return (1);
68869b1fd3fSRichard Lowe 			}
68969b1fd3fSRichard Lowe 
69069b1fd3fSRichard Lowe 			/*
69169b1fd3fSRichard Lowe 			 * If a msgid has been output a msgstr must follow
69269b1fd3fSRichard Lowe 			 * before we digest the new token.  A msgid is only set
69369b1fd3fSRichard Lowe 			 * if fdmsgs is in use.
69469b1fd3fSRichard Lowe 			 */
69569b1fd3fSRichard Lowe 			if (msgid) {
69669b1fd3fSRichard Lowe 				msgid = 0;
69769b1fd3fSRichard Lowe 				if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) {
69869b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
69969b1fd3fSRichard Lowe 					    flmsgs, strerror(errno));
70069b1fd3fSRichard Lowe 					return (1);
70169b1fd3fSRichard Lowe 				}
70269b1fd3fSRichard Lowe 			}
70369b1fd3fSRichard Lowe 
70469b1fd3fSRichard Lowe 			/*
70569b1fd3fSRichard Lowe 			 * Pass lines directly through to the output message
70669b1fd3fSRichard Lowe 			 * file.
70769b1fd3fSRichard Lowe 			 */
70869b1fd3fSRichard Lowe 			if (fdmsgs && (prtmsgs == 1)) {
70969b1fd3fSRichard Lowe 				char	comment;
71069b1fd3fSRichard Lowe 
71169b1fd3fSRichard Lowe 				if (cflag == 0)
71269b1fd3fSRichard Lowe 					comment = '#';
71369b1fd3fSRichard Lowe 				else
71469b1fd3fSRichard Lowe 					comment = '$';
71569b1fd3fSRichard Lowe 
71669b1fd3fSRichard Lowe 				if (fprintf(fdmsgs, "%c%s", comment,
71769b1fd3fSRichard Lowe 				    ++token) < 0) {
71869b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
71969b1fd3fSRichard Lowe 					    flmsgs, strerror(errno));
72069b1fd3fSRichard Lowe 					return (1);
72169b1fd3fSRichard Lowe 				}
72269b1fd3fSRichard Lowe 			}
72369b1fd3fSRichard Lowe 			break;
72469b1fd3fSRichard Lowe 
72569b1fd3fSRichard Lowe 		case '@':
72669b1fd3fSRichard Lowe 			if (escape) {
72769b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_malt, fldesc,
72869b1fd3fSRichard Lowe 				    line);
72969b1fd3fSRichard Lowe 				return (1);
73069b1fd3fSRichard Lowe 			}
73169b1fd3fSRichard Lowe 
73269b1fd3fSRichard Lowe 			/*
73369b1fd3fSRichard Lowe 			 * If a msgid has been output a msgstr must follow
73469b1fd3fSRichard Lowe 			 * before we digest the new token.
73569b1fd3fSRichard Lowe 			 */
73669b1fd3fSRichard Lowe 			if (msgid) {
73769b1fd3fSRichard Lowe 				msgid = 0;
73869b1fd3fSRichard Lowe 				if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) {
73969b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
74069b1fd3fSRichard Lowe 					    flmsgs, strerror(errno));
74169b1fd3fSRichard Lowe 					return (1);
74269b1fd3fSRichard Lowe 				}
74369b1fd3fSRichard Lowe 			}
74469b1fd3fSRichard Lowe 
74569b1fd3fSRichard Lowe 			/*
74669b1fd3fSRichard Lowe 			 * Determine whether we have one or more tokens.
74769b1fd3fSRichard Lowe 			 */
74869b1fd3fSRichard Lowe 			token++;
74969b1fd3fSRichard Lowe 			while (isspace(*token))		/* rid any whitespace */
75069b1fd3fSRichard Lowe 				token++;
75169b1fd3fSRichard Lowe 			_defn = token;			/* definition start */
75269b1fd3fSRichard Lowe 			while (!(isspace(*token)))
75369b1fd3fSRichard Lowe 				token++;
75469b1fd3fSRichard Lowe 			*token++ = 0;
75569b1fd3fSRichard Lowe 
75669b1fd3fSRichard Lowe 			while (isspace(*token))		/* rid any whitespace */
75769b1fd3fSRichard Lowe 				token++;
75869b1fd3fSRichard Lowe 
75969b1fd3fSRichard Lowe 			/*
76069b1fd3fSRichard Lowe 			 * Determine whether the single token is one of the
76169b1fd3fSRichard Lowe 			 * reserved message output delimiters otherwise
76269b1fd3fSRichard Lowe 			 * translate it as a message identifier.
76369b1fd3fSRichard Lowe 			 */
76469b1fd3fSRichard Lowe 			if (*token == 0) {
76569b1fd3fSRichard Lowe 				if (strcmp(_defn, start) == 0)
76669b1fd3fSRichard Lowe 					prtmsgs = 1;
76769b1fd3fSRichard Lowe 				else if (strcmp(_defn, end) == 0)
76869b1fd3fSRichard Lowe 					prtmsgs = -1;
76969b1fd3fSRichard Lowe 				else if (getmesgid(_defn) == 1)
77069b1fd3fSRichard Lowe 					return (1);
77169b1fd3fSRichard Lowe 				break;
77269b1fd3fSRichard Lowe 			}
77369b1fd3fSRichard Lowe 
77469b1fd3fSRichard Lowe 			/*
77569b1fd3fSRichard Lowe 			 * Multiple tokens are translated by taking the first
77669b1fd3fSRichard Lowe 			 * token as the message definition, and the rest of the
77769b1fd3fSRichard Lowe 			 * line as the message itself.  A message line ending
77869b1fd3fSRichard Lowe 			 * with an escape ('\') is expected to be continued on
77969b1fd3fSRichard Lowe 			 * the next line.
78069b1fd3fSRichard Lowe 			 */
78169b1fd3fSRichard Lowe 			if (prtmsgs != -1)
78269b1fd3fSRichard Lowe 				prtmsgs = 1;
78369b1fd3fSRichard Lowe 			if (fdmsgs && (prtmsgs == 1)) {
78469b1fd3fSRichard Lowe 				/*
78569b1fd3fSRichard Lowe 				 * For catgets(3c) make sure a message
78669b1fd3fSRichard Lowe 				 * identifier has been established (this is
787*4b9db4f6SChris Fraire 				 * normally a domain for gettext(3C), but for
78869b1fd3fSRichard Lowe 				 * sgsmsg use this could be argued as being
78969b1fd3fSRichard Lowe 				 * redundent).  Also make sure that the message
79069b1fd3fSRichard Lowe 				 * definitions haven't exceeeded the maximum
79169b1fd3fSRichard Lowe 				 * value allowed by gencat(1) before generating
79269b1fd3fSRichard Lowe 				 * any message file entries.
79369b1fd3fSRichard Lowe 				 */
79469b1fd3fSRichard Lowe 				if (cflag == 1) {
79569b1fd3fSRichard Lowe 					if (setid == 0) {
79669b1fd3fSRichard Lowe 						(void) fprintf(stderr, "file "
79769b1fd3fSRichard Lowe 						    "%s: no message identifier "
79869b1fd3fSRichard Lowe 						    "has been established\n",
79969b1fd3fSRichard Lowe 						    fldesc);
80069b1fd3fSRichard Lowe 						return (1);
80169b1fd3fSRichard Lowe 					}
80269b1fd3fSRichard Lowe 					if (ptr	> NL_MSGMAX) {
80369b1fd3fSRichard Lowe 						(void) fprintf(stderr, "file "
80469b1fd3fSRichard Lowe 						    "%s: message definition "
80569b1fd3fSRichard Lowe 						    "(%d) exceeds allowable "
80669b1fd3fSRichard Lowe 						    "limit (NL_MSGMAX)\n",
80769b1fd3fSRichard Lowe 						    fldesc, ptr);
80869b1fd3fSRichard Lowe 						return (1);
80969b1fd3fSRichard Lowe 					}
81069b1fd3fSRichard Lowe 				}
81169b1fd3fSRichard Lowe 
81269b1fd3fSRichard Lowe 				/*
81369b1fd3fSRichard Lowe 				 * For catgets(3c) write the definition and the
81469b1fd3fSRichard Lowe 				 * message string to the message file.  For
815*4b9db4f6SChris Fraire 				 * gettext(3C) write the message string as a
81669b1fd3fSRichard Lowe 				 * mesgid - indicate a mesgid has been output
81769b1fd3fSRichard Lowe 				 * so that a msgstr can follow.
81869b1fd3fSRichard Lowe 				 */
81969b1fd3fSRichard Lowe 				if (cflag == 1) {
82069b1fd3fSRichard Lowe 					if (fprintf(fdmsgs, "%d\t%s", ptr,
82169b1fd3fSRichard Lowe 					    token) < 0) {
82269b1fd3fSRichard Lowe 						(void) fprintf(stderr,
82369b1fd3fSRichard Lowe 						    Errmsg_wrte, flmsgs,
82469b1fd3fSRichard Lowe 						    strerror(errno));
82569b1fd3fSRichard Lowe 						return (1);
82669b1fd3fSRichard Lowe 					}
82769b1fd3fSRichard Lowe 				} else {
82869b1fd3fSRichard Lowe 					if (fprintf(fdmsgs, "msgid\t\"") < 0) {
82969b1fd3fSRichard Lowe 						(void) fprintf(stderr,
83069b1fd3fSRichard Lowe 						    Errmsg_wrte, flmsgs,
83169b1fd3fSRichard Lowe 						    strerror(errno));
83269b1fd3fSRichard Lowe 						return (1);
83369b1fd3fSRichard Lowe 					}
83469b1fd3fSRichard Lowe 					msgid = 1;
83569b1fd3fSRichard Lowe 				}
83669b1fd3fSRichard Lowe 			}
83769b1fd3fSRichard Lowe 
83869b1fd3fSRichard Lowe 			/*
83969b1fd3fSRichard Lowe 			 * The message itself is a quoted string as this makes
84069b1fd3fSRichard Lowe 			 * embedding spaces at the start (or the end) of the
84169b1fd3fSRichard Lowe 			 * string very easy.
84269b1fd3fSRichard Lowe 			 */
84369b1fd3fSRichard Lowe 			if (*token != '"') {
84469b1fd3fSRichard Lowe 				(void) fprintf(stderr, Errmsg_malt, fldesc,
84569b1fd3fSRichard Lowe 				    line);
84669b1fd3fSRichard Lowe 				return (1);
84769b1fd3fSRichard Lowe 			}
84869b1fd3fSRichard Lowe 
84969b1fd3fSRichard Lowe 			(void) strcpy(defn, _defn);
85069b1fd3fSRichard Lowe 
85169b1fd3fSRichard Lowe 			/*
85269b1fd3fSRichard Lowe 			 * Write the tag to the lint definitions.
85369b1fd3fSRichard Lowe 			 */
85469b1fd3fSRichard Lowe 			if (fdlint) {
85569b1fd3fSRichard Lowe 				if (fprintf(fdlint, "\n#define\t%s\t",
85669b1fd3fSRichard Lowe 				    _defn) < 0) {
85769b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
85869b1fd3fSRichard Lowe 					    fllint, strerror(errno));
85969b1fd3fSRichard Lowe 					return (1);
86069b1fd3fSRichard Lowe 				}
86169b1fd3fSRichard Lowe 			}
86269b1fd3fSRichard Lowe 
86369b1fd3fSRichard Lowe 			len = 0;
86469b1fd3fSRichard Lowe 
86569b1fd3fSRichard Lowe 			/*
86669b1fd3fSRichard Lowe 			 * Write each character of the message string to the
86769b1fd3fSRichard Lowe 			 * data array.  Translate any escaped characters - use
86869b1fd3fSRichard Lowe 			 * the same specially recognized characters as defined
86969b1fd3fSRichard Lowe 			 * by gencat(1).
87069b1fd3fSRichard Lowe 			 */
87169b1fd3fSRichard Lowe message:
87269b1fd3fSRichard Lowe 			if (*token == '"') {
87369b1fd3fSRichard Lowe 				if (fdlint &&
87469b1fd3fSRichard Lowe 				    (fprintf(fdlint, "%c", *token) < 0)) {
87569b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
87669b1fd3fSRichard Lowe 					    fllint, strerror(errno));
87769b1fd3fSRichard Lowe 					return (1);
87869b1fd3fSRichard Lowe 				}
87969b1fd3fSRichard Lowe 				token++;
88069b1fd3fSRichard Lowe 			}
88169b1fd3fSRichard Lowe 			while (*token) {
88269b1fd3fSRichard Lowe 				char	_token;
88369b1fd3fSRichard Lowe 
88469b1fd3fSRichard Lowe 				if ((*token == '\\') && (escape == 0)) {
88569b1fd3fSRichard Lowe 					escape = 1;
88669b1fd3fSRichard Lowe 					if (fdlint && (*(token + 1) != '\n') &&
88769b1fd3fSRichard Lowe 					    fprintf(fdlint, "%c", *token) < 0) {
88869b1fd3fSRichard Lowe 						(void) fprintf(stderr,
88969b1fd3fSRichard Lowe 						    Errmsg_wrte, fllint,
89069b1fd3fSRichard Lowe 						    strerror(errno));
89169b1fd3fSRichard Lowe 						return (1);
89269b1fd3fSRichard Lowe 					}
89369b1fd3fSRichard Lowe 					token++;
89469b1fd3fSRichard Lowe 					continue;
89569b1fd3fSRichard Lowe 				}
89669b1fd3fSRichard Lowe 				if (escape) {
89769b1fd3fSRichard Lowe 					if (*token == 'n')
89869b1fd3fSRichard Lowe 						_token = '\n';
89969b1fd3fSRichard Lowe 					else if (*token == 't')
90069b1fd3fSRichard Lowe 						_token = '\t';
90169b1fd3fSRichard Lowe 					else if (*token == 'v')
90269b1fd3fSRichard Lowe 						_token = '\v';
90369b1fd3fSRichard Lowe 					else if (*token == 'b')
90469b1fd3fSRichard Lowe 						_token = '\b';
90569b1fd3fSRichard Lowe 					else if (*token == 'f')
90669b1fd3fSRichard Lowe 						_token = '\f';
90769b1fd3fSRichard Lowe 					else if (*token == '\\')
90869b1fd3fSRichard Lowe 						_token = '\\';
90969b1fd3fSRichard Lowe 					else if (*token == '"')
91069b1fd3fSRichard Lowe 						_token = '"';
91169b1fd3fSRichard Lowe 					else if (*token == '\n')
91269b1fd3fSRichard Lowe 						break;
91369b1fd3fSRichard Lowe 					else
91469b1fd3fSRichard Lowe 						_token = *token;
91569b1fd3fSRichard Lowe 
91669b1fd3fSRichard Lowe 					if (fdmsgs && (prtmsgs == 1) &&
91769b1fd3fSRichard Lowe 					    (fprintf(fdmsgs, "\\") < 0)) {
91869b1fd3fSRichard Lowe 						(void) fprintf(stderr,
91969b1fd3fSRichard Lowe 						    Errmsg_wrte, flmsgs,
92069b1fd3fSRichard Lowe 						    strerror(errno));
92169b1fd3fSRichard Lowe 						return (1);
92269b1fd3fSRichard Lowe 					}
92369b1fd3fSRichard Lowe 				} else {
92469b1fd3fSRichard Lowe 					/*
92569b1fd3fSRichard Lowe 					 * If this is the trailing quote then
92669b1fd3fSRichard Lowe 					 * thats the last of the message string.
92769b1fd3fSRichard Lowe 					 * Eat up any remaining white space and
92869b1fd3fSRichard Lowe 					 * unless an escape character is found
92969b1fd3fSRichard Lowe 					 * terminate the data string with a 0.
93069b1fd3fSRichard Lowe 					 */
93169b1fd3fSRichard Lowe 					/* BEGIN CSTYLED */
93269b1fd3fSRichard Lowe 					if (*token == '"') {
93369b1fd3fSRichard Lowe 					    if (fdlint && (fprintf(fdlint,
93469b1fd3fSRichard Lowe 						"%c", *token) < 0)) {
93569b1fd3fSRichard Lowe 						(void) fprintf(stderr,
93669b1fd3fSRichard Lowe 						    Errmsg_wrte, fllint,
93769b1fd3fSRichard Lowe 						    strerror(errno));
93869b1fd3fSRichard Lowe 						return (1);
93969b1fd3fSRichard Lowe 					    }
94069b1fd3fSRichard Lowe 
94169b1fd3fSRichard Lowe 					    if (fdmsgs && (prtmsgs == 1) &&
94269b1fd3fSRichard Lowe 						(fprintf(fdmsgs, "%c",
94369b1fd3fSRichard Lowe 						*token) < 0)) {
94469b1fd3fSRichard Lowe 						(void) fprintf(stderr,
94569b1fd3fSRichard Lowe 						    Errmsg_wrte, flmsgs,
94669b1fd3fSRichard Lowe 						    strerror(errno));
94769b1fd3fSRichard Lowe 						return (1);
94869b1fd3fSRichard Lowe 					    }
94969b1fd3fSRichard Lowe 
95069b1fd3fSRichard Lowe 					    while (*++token) {
95169b1fd3fSRichard Lowe 						if (*token == '\n')
95269b1fd3fSRichard Lowe 							break;
95369b1fd3fSRichard Lowe 					    }
95469b1fd3fSRichard Lowe 					    _token = '\0';
95569b1fd3fSRichard Lowe 					} else
95669b1fd3fSRichard Lowe 					    _token = *token;
95769b1fd3fSRichard Lowe 					/* END CSTYLED */
95869b1fd3fSRichard Lowe 				}
95969b1fd3fSRichard Lowe 
96069b1fd3fSRichard Lowe 				if (fdmsgs && (prtmsgs == 1) &&
96169b1fd3fSRichard Lowe 				    (fprintf(fdmsgs, "%c", *token) < 0)) {
96269b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
96369b1fd3fSRichard Lowe 					    flmsgs, strerror(errno));
96469b1fd3fSRichard Lowe 					return (1);
96569b1fd3fSRichard Lowe 				}
96669b1fd3fSRichard Lowe 
96769b1fd3fSRichard Lowe 				if (fdlint && fprintf(fdlint,
96869b1fd3fSRichard Lowe 				    "%c", *token) < 0) {
96969b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
97069b1fd3fSRichard Lowe 					    fllint, strerror(errno));
97169b1fd3fSRichard Lowe 					return (1);
97269b1fd3fSRichard Lowe 				}
97369b1fd3fSRichard Lowe 
97469b1fd3fSRichard Lowe 				if (len >= bufsize) {
97569b1fd3fSRichard Lowe 					bufsize += LINE_MAX;
97669b1fd3fSRichard Lowe 					if ((token_buffer = realloc(
97769b1fd3fSRichard Lowe 					    token_buffer, bufsize)) == 0) {
97869b1fd3fSRichard Lowe 						(void) fprintf(stderr,
97969b1fd3fSRichard Lowe 						    Errmsg_nmem,
98069b1fd3fSRichard Lowe 						    strerror(errno));
98169b1fd3fSRichard Lowe 						return (1);
98269b1fd3fSRichard Lowe 					}
98369b1fd3fSRichard Lowe 				}
98469b1fd3fSRichard Lowe 				token_buffer[len] = _token;
98569b1fd3fSRichard Lowe 				ptr++, token++, len++;
98669b1fd3fSRichard Lowe 				escape = 0;
98769b1fd3fSRichard Lowe 
98869b1fd3fSRichard Lowe 				if (_token == '\0')
98969b1fd3fSRichard Lowe 					break;
99069b1fd3fSRichard Lowe 			}
99169b1fd3fSRichard Lowe 
99269b1fd3fSRichard Lowe 			/*
99369b1fd3fSRichard Lowe 			 * After the complete message string has been processed
99469b1fd3fSRichard Lowe 			 * (including its continuation beyond one line), create
99569b1fd3fSRichard Lowe 			 * a string size definition.
99669b1fd3fSRichard Lowe 			 */
99769b1fd3fSRichard Lowe 			if (escape == 0) {
99869b1fd3fSRichard Lowe 				const char *form = "#define\t%s_SIZE\t%d\n";
99969b1fd3fSRichard Lowe 
100069b1fd3fSRichard Lowe 				token_buffer[len] = '\0';
100169b1fd3fSRichard Lowe 
100269b1fd3fSRichard Lowe 				message_append(defn, token_buffer);
100369b1fd3fSRichard Lowe 
100469b1fd3fSRichard Lowe 				if (fdlint && fprintf(fdlint, form, defn,
100569b1fd3fSRichard Lowe 				    (len - 1)) < 0) {
100669b1fd3fSRichard Lowe 					(void) fprintf(stderr, Errmsg_wrte,
100769b1fd3fSRichard Lowe 					    fllint, strerror(errno));
100869b1fd3fSRichard Lowe 					return (1);
100969b1fd3fSRichard Lowe 				}
101069b1fd3fSRichard Lowe 			}
101169b1fd3fSRichard Lowe 			break;
101269b1fd3fSRichard Lowe 
101369b1fd3fSRichard Lowe 		default:
101469b1fd3fSRichard Lowe 			/*
101569b1fd3fSRichard Lowe 			 * Empty lines are passed through to the message file.
101669b1fd3fSRichard Lowe 			 */
101769b1fd3fSRichard Lowe 			while (isspace(*token))
101869b1fd3fSRichard Lowe 				token++;
101969b1fd3fSRichard Lowe 
102069b1fd3fSRichard Lowe 			if (*token == 0) {
102169b1fd3fSRichard Lowe 				if (msgid || (fdmsgs && (prtmsgs == 1))) {
102269b1fd3fSRichard Lowe 					/*
102369b1fd3fSRichard Lowe 					 * If a msgid has been output a msgstr
102469b1fd3fSRichard Lowe 					 * must follow before we digest the new
102569b1fd3fSRichard Lowe 					 * token.
102669b1fd3fSRichard Lowe 					 */
102769b1fd3fSRichard Lowe 					if (msgid) {
102869b1fd3fSRichard Lowe 						msgid = 0;
102969b1fd3fSRichard Lowe 						str = "msgstr\t\"\"\n\n";
103069b1fd3fSRichard Lowe 					} else
103169b1fd3fSRichard Lowe 						str = "\n";
103269b1fd3fSRichard Lowe 
103369b1fd3fSRichard Lowe 					if (fprintf(fdmsgs, str) < 0) {
103469b1fd3fSRichard Lowe 						(void) fprintf(stderr,
103569b1fd3fSRichard Lowe 						    Errmsg_wrte, flmsgs,
103669b1fd3fSRichard Lowe 						    strerror(errno));
103769b1fd3fSRichard Lowe 						return (1);
103869b1fd3fSRichard Lowe 					}
103969b1fd3fSRichard Lowe 				}
104069b1fd3fSRichard Lowe 				break;
104169b1fd3fSRichard Lowe 			}
104269b1fd3fSRichard Lowe 
104369b1fd3fSRichard Lowe 			/*
104469b1fd3fSRichard Lowe 			 * If an escape is in effect then any tokens are taken
104569b1fd3fSRichard Lowe 			 * to be message continuations.
104669b1fd3fSRichard Lowe 			 */
104769b1fd3fSRichard Lowe 			if (escape) {
104869b1fd3fSRichard Lowe 				escape = 0;
104969b1fd3fSRichard Lowe 				goto message;
105069b1fd3fSRichard Lowe 			}
105169b1fd3fSRichard Lowe 
105269b1fd3fSRichard Lowe 			(void) fprintf(stderr, "file %s: line %d: invalid "
105369b1fd3fSRichard Lowe 			    "input does not start with #, $ or @\n", fldesc,
105469b1fd3fSRichard Lowe 			    line);
105569b1fd3fSRichard Lowe 			return (1);
105669b1fd3fSRichard Lowe 		}
105769b1fd3fSRichard Lowe 		line++;
105869b1fd3fSRichard Lowe 	}
105969b1fd3fSRichard Lowe 
106069b1fd3fSRichard Lowe 	free(token_buffer);
106169b1fd3fSRichard Lowe 
106269b1fd3fSRichard Lowe 	return (0);
106369b1fd3fSRichard Lowe }
106469b1fd3fSRichard Lowe 
106569b1fd3fSRichard Lowe int
main(int argc,char ** argv)106669b1fd3fSRichard Lowe main(int argc, char ** argv)
106769b1fd3fSRichard Lowe {
106869b1fd3fSRichard Lowe 	opterr = 0;
106969b1fd3fSRichard Lowe 	while ((line = getopt(argc, argv, "cd:h:lm:n:i:v")) != EOF) {
107069b1fd3fSRichard Lowe 		switch (line) {
107169b1fd3fSRichard Lowe 		case 'c':			/* catgets instead of gettext */
107269b1fd3fSRichard Lowe 			cflag = 1;
107369b1fd3fSRichard Lowe 			break;
107469b1fd3fSRichard Lowe 		case 'd':			/* new message data filename */
107569b1fd3fSRichard Lowe 			fldata = optarg;	/*	(msg.c is default) */
107669b1fd3fSRichard Lowe 			break;
107769b1fd3fSRichard Lowe 		case 'h':			/* new message defs filename */
107869b1fd3fSRichard Lowe 			fldefs = optarg;	/*	(msg.h is default) */
107969b1fd3fSRichard Lowe 			break;
108069b1fd3fSRichard Lowe 		case 'i':			/* input message ids from */
108169b1fd3fSRichard Lowe 			flmids = optarg;	/*	from this file */
108269b1fd3fSRichard Lowe 			break;
108369b1fd3fSRichard Lowe 		case 'l':			/* define message data arrays */
108469b1fd3fSRichard Lowe 			lflag = 1;		/*	to be local (static) */
108569b1fd3fSRichard Lowe 			break;
108669b1fd3fSRichard Lowe 		case 'm':			/* generate message database */
108769b1fd3fSRichard Lowe 			flmsgs = optarg;	/*	to this file */
108869b1fd3fSRichard Lowe 			break;
108969b1fd3fSRichard Lowe 		case 'n':			/* new data array and func */
109069b1fd3fSRichard Lowe 			interface = optarg;	/*	name (msg is default) */
109169b1fd3fSRichard Lowe 			break;
109269b1fd3fSRichard Lowe 		case 'v':
109369b1fd3fSRichard Lowe 			vflag = 1;		/* set verbose flag */
109469b1fd3fSRichard Lowe 			break;
109569b1fd3fSRichard Lowe 		case '?':
109669b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_use, argv[0]);
109769b1fd3fSRichard Lowe 			exit(1);
109869b1fd3fSRichard Lowe 		default:
109969b1fd3fSRichard Lowe 			break;
110069b1fd3fSRichard Lowe 		}
110169b1fd3fSRichard Lowe 	}
110269b1fd3fSRichard Lowe 
110369b1fd3fSRichard Lowe 	/*
110469b1fd3fSRichard Lowe 	 * Validate the we have been given at least one input file.
110569b1fd3fSRichard Lowe 	 */
110669b1fd3fSRichard Lowe 	if ((argc - optind) < 1) {
110769b1fd3fSRichard Lowe 		(void) fprintf(stderr, Errmsg_use);
110869b1fd3fSRichard Lowe 		exit(1);
110969b1fd3fSRichard Lowe 	}
111069b1fd3fSRichard Lowe 
111169b1fd3fSRichard Lowe 	/*
111269b1fd3fSRichard Lowe 	 * Open all the required output files.
111369b1fd3fSRichard Lowe 	 */
111469b1fd3fSRichard Lowe 	if (fldefs) {
111569b1fd3fSRichard Lowe 		if ((fddefs = fopen(fldefs, "w+")) == NULL) {
111669b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, fldefs,
111769b1fd3fSRichard Lowe 			    strerror(errno));
111869b1fd3fSRichard Lowe 			return (1);
111969b1fd3fSRichard Lowe 		}
112069b1fd3fSRichard Lowe 	}
112169b1fd3fSRichard Lowe 	if (fldata) {
112269b1fd3fSRichard Lowe 		if (fldefs && (strcmp(fldefs, fldata) == 0))
112369b1fd3fSRichard Lowe 			fddata = fddefs;
112469b1fd3fSRichard Lowe 		else if ((fddata = fopen(fldata, "w+")) == NULL) {
112569b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, fldata,
112669b1fd3fSRichard Lowe 			    strerror(errno));
112769b1fd3fSRichard Lowe 			return (1);
112869b1fd3fSRichard Lowe 		}
112969b1fd3fSRichard Lowe 	}
113069b1fd3fSRichard Lowe 	if (fddefs && fddata) {
113169b1fd3fSRichard Lowe 		(void) sprintf(fllint, "%s.%d.XXXXXX", nmlint, (int)getpid());
113269b1fd3fSRichard Lowe 		if ((mkstemp(fllint) == -1) ||
113369b1fd3fSRichard Lowe 		    ((fdlint = fopen(fllint, "w+")) == NULL)) {
113469b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, fllint,
113569b1fd3fSRichard Lowe 			    strerror(errno));
113669b1fd3fSRichard Lowe 			return (1);
113769b1fd3fSRichard Lowe 		}
113869b1fd3fSRichard Lowe 	}
113969b1fd3fSRichard Lowe 	if (flmsgs) {
114069b1fd3fSRichard Lowe 		if ((fdmsgs = fopen(flmsgs, "w+")) == NULL) {
114169b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, flmsgs,
114269b1fd3fSRichard Lowe 			    strerror(errno));
114369b1fd3fSRichard Lowe 			return (1);
114469b1fd3fSRichard Lowe 		}
114569b1fd3fSRichard Lowe 	}
114669b1fd3fSRichard Lowe 	if (flmids) {
114769b1fd3fSRichard Lowe 		if ((fdmids = fopen(flmids, "r")) == NULL) {
114869b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, flmids,
114969b1fd3fSRichard Lowe 			    strerror(errno));
115069b1fd3fSRichard Lowe 			return (1);
115169b1fd3fSRichard Lowe 		}
115269b1fd3fSRichard Lowe 	}
115369b1fd3fSRichard Lowe 
115469b1fd3fSRichard Lowe 
115569b1fd3fSRichard Lowe 	/*
115669b1fd3fSRichard Lowe 	 * Initialize the message definition and message data streams.
115769b1fd3fSRichard Lowe 	 */
115869b1fd3fSRichard Lowe 	if (fddefs) {
115969b1fd3fSRichard Lowe 		if (init_defs())
116069b1fd3fSRichard Lowe 			return (1);
116169b1fd3fSRichard Lowe 	}
116269b1fd3fSRichard Lowe 
116369b1fd3fSRichard Lowe 	/*
116469b1fd3fSRichard Lowe 	 * Read the input message file, and for each line process accordingly.
116569b1fd3fSRichard Lowe 	 */
116669b1fd3fSRichard Lowe 	for (; optind < argc; optind++) {
116769b1fd3fSRichard Lowe 		int	err;
116869b1fd3fSRichard Lowe 
116969b1fd3fSRichard Lowe 		fldesc = argv[optind];
117069b1fd3fSRichard Lowe 
117169b1fd3fSRichard Lowe 		if ((fddesc = fopen(fldesc, "r")) == NULL) {
117269b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_opne, fldesc,
117369b1fd3fSRichard Lowe 			    strerror(errno));
117469b1fd3fSRichard Lowe 			return (1);
117569b1fd3fSRichard Lowe 		}
117669b1fd3fSRichard Lowe 		err = file();
117769b1fd3fSRichard Lowe 		(void) fclose(fddesc);
117869b1fd3fSRichard Lowe 
117969b1fd3fSRichard Lowe 		if (err != 0)
118069b1fd3fSRichard Lowe 			return (1);
118169b1fd3fSRichard Lowe 	}
118269b1fd3fSRichard Lowe 
118369b1fd3fSRichard Lowe 	/*
118469b1fd3fSRichard Lowe 	 * If a msgid has been output a msgstr must follow before we end the
118569b1fd3fSRichard Lowe 	 * file.
118669b1fd3fSRichard Lowe 	 */
118769b1fd3fSRichard Lowe 	if (msgid) {
118869b1fd3fSRichard Lowe 		msgid = 0;
118969b1fd3fSRichard Lowe 		if (fprintf(fdmsgs, "msgstr\t\"\"\n") < 0) {
119069b1fd3fSRichard Lowe 			(void) fprintf(stderr, Errmsg_wrte, flmsgs,
119169b1fd3fSRichard Lowe 			    strerror(errno));
119269b1fd3fSRichard Lowe 			return (1);
119369b1fd3fSRichard Lowe 		}
119469b1fd3fSRichard Lowe 	}
119569b1fd3fSRichard Lowe 
119669b1fd3fSRichard Lowe 	if (fdmids)
119769b1fd3fSRichard Lowe 		(void) fclose(fdmids);
119869b1fd3fSRichard Lowe 	if (fdmsgs)
119969b1fd3fSRichard Lowe 		(void) fclose(fdmsgs);
120069b1fd3fSRichard Lowe 
120169b1fd3fSRichard Lowe 	if (fddefs) {
120269b1fd3fSRichard Lowe 		if (output_defs())
120369b1fd3fSRichard Lowe 			return (1);
120469b1fd3fSRichard Lowe 	}
120569b1fd3fSRichard Lowe 
120669b1fd3fSRichard Lowe 	/*
120769b1fd3fSRichard Lowe 	 * Finish off any generated data and header file.
120869b1fd3fSRichard Lowe 	 */
120969b1fd3fSRichard Lowe 	if (fldata) {
121069b1fd3fSRichard Lowe 		if (output_data())
121169b1fd3fSRichard Lowe 			return (1);
121269b1fd3fSRichard Lowe 	}
121369b1fd3fSRichard Lowe 	if (fddefs) {
121469b1fd3fSRichard Lowe 		if (fini_defs())
121569b1fd3fSRichard Lowe 			return (1);
121669b1fd3fSRichard Lowe 	}
121769b1fd3fSRichard Lowe 
121869b1fd3fSRichard Lowe 	if (vflag)
121969b1fd3fSRichard Lowe 		dump_stringtab(stp);
122069b1fd3fSRichard Lowe 
122169b1fd3fSRichard Lowe 	/*
122269b1fd3fSRichard Lowe 	 * Close up everything and go home.
122369b1fd3fSRichard Lowe 	 */
122469b1fd3fSRichard Lowe 	if (fddata)
122569b1fd3fSRichard Lowe 		(void) fclose(fddata);
122669b1fd3fSRichard Lowe 	if (fddefs && (fddefs != fddata))
122769b1fd3fSRichard Lowe 		(void) fclose(fddefs);
122869b1fd3fSRichard Lowe 	if (fddefs && fddata) {
122969b1fd3fSRichard Lowe 		(void) fclose(fdlint);
123069b1fd3fSRichard Lowe 		(void) unlink(fllint);
123169b1fd3fSRichard Lowe 	}
123269b1fd3fSRichard Lowe 
123369b1fd3fSRichard Lowe 	if (stp)
123469b1fd3fSRichard Lowe 		st_destroy(stp);
123569b1fd3fSRichard Lowe 
123669b1fd3fSRichard Lowe 	return (0);
123769b1fd3fSRichard Lowe }
1238