xref: /illumos-gate/usr/src/cmd/msgfmt/xgettext.c (revision df69b316)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 1991, 1999, 2001-2002 Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include	<ctype.h>
297c478bd9Sstevel@tonic-gate #include	<stdio.h>
307c478bd9Sstevel@tonic-gate #include	<stdlib.h>
317c478bd9Sstevel@tonic-gate #include	<string.h>
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #define	TRUE	1
347c478bd9Sstevel@tonic-gate #define	FALSE	0
357c478bd9Sstevel@tonic-gate #define	MAX_PATH_LEN	1024
367c478bd9Sstevel@tonic-gate #define	MAX_DOMAIN_LEN	1024
377c478bd9Sstevel@tonic-gate #define	MAX_STRING_LEN  2048
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate #define	USAGE	"Usage:	xgettext [-a [-x exclude-file]] [-jns]\
407c478bd9Sstevel@tonic-gate [-c comment-tag]\n	[-d default-domain] [-m prefix] \
417c478bd9Sstevel@tonic-gate [-M suffix] [-p pathname] files ...\n\
427c478bd9Sstevel@tonic-gate 	xgettext -h\n"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #define	DEFAULT_DOMAIN	"messages"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate extern char	yytext[];
477c478bd9Sstevel@tonic-gate extern int	yylex(void);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Contains a list of strings to be used to store ANSI-C style string.
517c478bd9Sstevel@tonic-gate  * Each quoted string is stored in one node.
527c478bd9Sstevel@tonic-gate  */
537c478bd9Sstevel@tonic-gate struct strlist_st {
547c478bd9Sstevel@tonic-gate 	char			*str;
557c478bd9Sstevel@tonic-gate 	struct strlist_st	*next;
567c478bd9Sstevel@tonic-gate };
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate  * istextdomain	: Boolean telling if this node contains textdomain call.
60*df69b316SToomas Soome  * isduplicate	: Boolean telling if this node duplicate of any other msgid.
617c478bd9Sstevel@tonic-gate  * msgid	: contains msgid or textdomain if istextdomain is true.
627c478bd9Sstevel@tonic-gate  * msgstr	: contains msgstr.
637c478bd9Sstevel@tonic-gate  * comment	: comment extracted in case of -c option.
647c478bd9Sstevel@tonic-gate  * fname	: tells which file contains msgid.
657c478bd9Sstevel@tonic-gate  * linenum	: line number in the file.
66*df69b316SToomas Soome  * next		: Next node.
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate struct element_st {
697c478bd9Sstevel@tonic-gate 	char			istextdomain;
707c478bd9Sstevel@tonic-gate 	char			isduplicate;
717c478bd9Sstevel@tonic-gate 	struct strlist_st	*msgid;
727c478bd9Sstevel@tonic-gate 	struct strlist_st	*msgstr;
737c478bd9Sstevel@tonic-gate 	struct strlist_st	*comment;
747c478bd9Sstevel@tonic-gate 	char			*fname;
757c478bd9Sstevel@tonic-gate 	int			linenum;
767c478bd9Sstevel@tonic-gate 	struct element_st	*next;
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * dname	   : domain name. NULL if default domain.
817c478bd9Sstevel@tonic-gate  * gettext_head    : Head of linked list containing [d]gettext().
827c478bd9Sstevel@tonic-gate  * gettext_tail    : Tail of linked list containing [d]gettext().
837c478bd9Sstevel@tonic-gate  * textdomain_head : Head of linked list containing textdomain().
847c478bd9Sstevel@tonic-gate  * textdomain_tail : Tail of linked list containing textdomain().
857c478bd9Sstevel@tonic-gate  * next		   : Next node.
867c478bd9Sstevel@tonic-gate  *
877c478bd9Sstevel@tonic-gate  * Each domain contains two linked list.
887c478bd9Sstevel@tonic-gate  *	(gettext_head,  textdomain_head)
897c478bd9Sstevel@tonic-gate  * If -s option is used, then textdomain_head contains all
907c478bd9Sstevel@tonic-gate  * textdomain() calls and no textdomain() calls are stored in gettext_head.
917c478bd9Sstevel@tonic-gate  * If -s option is not used, textdomain_head is empty list and
927c478bd9Sstevel@tonic-gate  * gettext_head contains all gettext() dgettext(), and textdomain() calls.
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate struct domain_st {
957c478bd9Sstevel@tonic-gate 	char			*dname;
967c478bd9Sstevel@tonic-gate 	struct element_st	*gettext_head;
977c478bd9Sstevel@tonic-gate 	struct element_st	*gettext_tail;
987c478bd9Sstevel@tonic-gate 	struct element_st	*textdomain_head;
997c478bd9Sstevel@tonic-gate 	struct element_st	*textdomain_tail;
1007c478bd9Sstevel@tonic-gate 	struct domain_st	*next;
1017c478bd9Sstevel@tonic-gate };
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate  * There are two domain linked lists.
1057c478bd9Sstevel@tonic-gate  * def_dom contains default domain linked list and
1067c478bd9Sstevel@tonic-gate  * dom_head contains all other deomain linked lists to be created by
1077c478bd9Sstevel@tonic-gate  * dgettext() calls.
1087c478bd9Sstevel@tonic-gate  */
1097c478bd9Sstevel@tonic-gate static struct domain_st	*def_dom = NULL;
1107c478bd9Sstevel@tonic-gate static struct domain_st	*dom_head = NULL;
1117c478bd9Sstevel@tonic-gate static struct domain_st	*dom_tail = NULL;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate  * This linked list contains a list of strings to be excluded when
1157c478bd9Sstevel@tonic-gate  * -x option is used.
1167c478bd9Sstevel@tonic-gate  */
1177c478bd9Sstevel@tonic-gate static struct exclude_st {
1187c478bd9Sstevel@tonic-gate 	struct strlist_st	*exstr;
1197c478bd9Sstevel@tonic-gate 	struct exclude_st	*next;
1207c478bd9Sstevel@tonic-gate } *excl_head;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /*
1237c478bd9Sstevel@tonic-gate  * All option flags and values for each option if any.
1247c478bd9Sstevel@tonic-gate  */
1257c478bd9Sstevel@tonic-gate static int	aflg = FALSE;
1267c478bd9Sstevel@tonic-gate static int	cflg = FALSE;
1277c478bd9Sstevel@tonic-gate static char	*comment_tag = NULL;
1287c478bd9Sstevel@tonic-gate static char	*default_domain = NULL;
1297c478bd9Sstevel@tonic-gate static int	hflg = FALSE;
1307c478bd9Sstevel@tonic-gate static int	jflg = FALSE;
1317c478bd9Sstevel@tonic-gate static int	mflg = FALSE;
1327c478bd9Sstevel@tonic-gate static int	Mflg = FALSE;
1337c478bd9Sstevel@tonic-gate static char	*suffix = NULL;
1347c478bd9Sstevel@tonic-gate static char	*prefix = NULL;
1357c478bd9Sstevel@tonic-gate static int	nflg = FALSE;
1367c478bd9Sstevel@tonic-gate static int	pflg = FALSE;
1377c478bd9Sstevel@tonic-gate static char	*pathname = NULL;
1387c478bd9Sstevel@tonic-gate static int	sflg = FALSE;
1397c478bd9Sstevel@tonic-gate static int	tflg = FALSE;	/* Undocumented option to extract dcgettext */
1407c478bd9Sstevel@tonic-gate static int	xflg = FALSE;
1417c478bd9Sstevel@tonic-gate static char	*exclude_file = NULL;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate  * Each variable shows the current state of parsing input file.
1457c478bd9Sstevel@tonic-gate  *
1467c478bd9Sstevel@tonic-gate  * in_comment    : Means inside comment block (C or C++).
1477c478bd9Sstevel@tonic-gate  * in_cplus_comment    : Means inside C++ comment block.
1487c478bd9Sstevel@tonic-gate  * in_gettext    : Means inside gettext call.
1497c478bd9Sstevel@tonic-gate  * in_dgettext   : Means inside dgettext call.
1507c478bd9Sstevel@tonic-gate  * in_dcgettext  : Means inside dcgettext call.
1517c478bd9Sstevel@tonic-gate  * in_textdomain : Means inside textdomain call.
1527c478bd9Sstevel@tonic-gate  * in_str	 : Means currently processing ANSI style string.
1537c478bd9Sstevel@tonic-gate  * in_quote	 : Means currently processing double quoted string.
1547c478bd9Sstevel@tonic-gate  * in_skippable_string	: Means currently processing double quoted string,
1557c478bd9Sstevel@tonic-gate  *                        that occurs outside a call to gettext, dgettext,
1567c478bd9Sstevel@tonic-gate  *                        dcgettext, textdomain, with -a not specified.
1577c478bd9Sstevel@tonic-gate  * is_last_comment_line : Means the current line is the last line
1587c478bd9Sstevel@tonic-gate  *			  of the comment block. This is necessary because
1597c478bd9Sstevel@tonic-gate  *			  in_comment becomes FALSE when '* /' is encountered.
1607c478bd9Sstevel@tonic-gate  * is_first_comma_found : This is used only for dcgettext because dcgettext()
1617c478bd9Sstevel@tonic-gate  *			  requires 2 commas. So need to do different action
1627c478bd9Sstevel@tonic-gate  *			  depending on which commas encountered.
1637c478bd9Sstevel@tonic-gate  * num_nested_open_paren : This keeps track of the number of open parens to
1647c478bd9Sstevel@tonic-gate  *			   handle dcgettext ((const char *)0,"msg",LC_TIME);
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate static int	in_comment		= FALSE;
1677c478bd9Sstevel@tonic-gate static int	in_cplus_comment	= FALSE;
1687c478bd9Sstevel@tonic-gate static int	in_gettext		= FALSE;
1697c478bd9Sstevel@tonic-gate static int	in_dgettext		= FALSE;
1707c478bd9Sstevel@tonic-gate static int	in_dcgettext		= FALSE;
1717c478bd9Sstevel@tonic-gate static int	in_textdomain		= FALSE;
1727c478bd9Sstevel@tonic-gate static int	in_str			= FALSE;
1737c478bd9Sstevel@tonic-gate static int	in_quote		= FALSE;
1747c478bd9Sstevel@tonic-gate static int	is_last_comment_line	= FALSE;
1757c478bd9Sstevel@tonic-gate static int	is_first_comma_found	= FALSE;
1767c478bd9Sstevel@tonic-gate static int	in_skippable_string	= FALSE;
1777c478bd9Sstevel@tonic-gate static int	num_nested_open_paren	= 0;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate  * This variable contains the first line of gettext(), dgettext(), or
1817c478bd9Sstevel@tonic-gate  * textdomain() calls.
1827c478bd9Sstevel@tonic-gate  * This is necessary for multiple lines of a single call to store
1837c478bd9Sstevel@tonic-gate  * the starting line.
1847c478bd9Sstevel@tonic-gate  */
1857c478bd9Sstevel@tonic-gate static int	linenum_saved = 0;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate int	stdin_only = FALSE;	/* Read input from stdin */
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate  * curr_file    : Contains current file name processed.
1917c478bd9Sstevel@tonic-gate  * curr_domain  : Contains the current domain for each dgettext().
1927c478bd9Sstevel@tonic-gate  *		  This is NULL for gettext().
1937c478bd9Sstevel@tonic-gate  * curr_line    : Contains the current line processed.
1947c478bd9Sstevel@tonic-gate  * qstring_buf  : Contains the double quoted string processed.
1957c478bd9Sstevel@tonic-gate  * curr_linenum : Line number being processed in the current input file.
1967c478bd9Sstevel@tonic-gate  * warn_linenum : Line number of current warning message.
1977c478bd9Sstevel@tonic-gate  */
1987c478bd9Sstevel@tonic-gate char	curr_file[MAX_PATH_LEN];
1997c478bd9Sstevel@tonic-gate static char	curr_domain[MAX_DOMAIN_LEN];
2007c478bd9Sstevel@tonic-gate static char	curr_line[MAX_STRING_LEN];
2017c478bd9Sstevel@tonic-gate static char	qstring_buf[MAX_STRING_LEN];
2027c478bd9Sstevel@tonic-gate int	curr_linenum = 1;
2037c478bd9Sstevel@tonic-gate int	warn_linenum = 0;
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate /*
2067c478bd9Sstevel@tonic-gate  * strhead  : This list contains ANSI style string.
2077c478bd9Sstevel@tonic-gate  *		Each node contains double quoted string.
2087c478bd9Sstevel@tonic-gate  * strtail  : This is the tail of strhead.
2097c478bd9Sstevel@tonic-gate  * commhead : This list contains comments string.
2107c478bd9Sstevel@tonic-gate  *		Each node contains one line of comment.
2117c478bd9Sstevel@tonic-gate  * commtail : This is the tail of commhead.
2127c478bd9Sstevel@tonic-gate  */
2137c478bd9Sstevel@tonic-gate static struct strlist_st	*strhead = NULL;
2147c478bd9Sstevel@tonic-gate static struct strlist_st	*strtail = NULL;
2157c478bd9Sstevel@tonic-gate static struct strlist_st	*commhead = NULL;
2167c478bd9Sstevel@tonic-gate static struct strlist_st	*commtail = NULL;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate  * gargc : Same as argc. Used to pass argc to lex routine.
2207c478bd9Sstevel@tonic-gate  * gargv : Same as argv. Used to pass argc to lex routine.
2217c478bd9Sstevel@tonic-gate  */
2227c478bd9Sstevel@tonic-gate int	gargc;
2237c478bd9Sstevel@tonic-gate char	**gargv;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate static void add_line_to_comment(void);
2267c478bd9Sstevel@tonic-gate static void add_qstring_to_str(void);
2277c478bd9Sstevel@tonic-gate static void add_str_to_element_list(int, char *);
2287c478bd9Sstevel@tonic-gate static void copy_strlist_to_str(char *, struct strlist_st *);
2297c478bd9Sstevel@tonic-gate static void end_ansi_string(void);
2307c478bd9Sstevel@tonic-gate static void free_strlist(struct strlist_st *);
2317c478bd9Sstevel@tonic-gate void handle_newline(void);
2327c478bd9Sstevel@tonic-gate static void initialize_globals(void);
2337c478bd9Sstevel@tonic-gate static void output_comment(FILE *, struct strlist_st *);
2347c478bd9Sstevel@tonic-gate static void output_msgid(FILE *, struct strlist_st *, int);
2357c478bd9Sstevel@tonic-gate static void output_textdomain(FILE *, struct element_st *);
2367c478bd9Sstevel@tonic-gate static void print_help(void);
2377c478bd9Sstevel@tonic-gate static void read_exclude_file(void);
2387c478bd9Sstevel@tonic-gate static void trim_line(char *);
2397c478bd9Sstevel@tonic-gate static void write_all_files(void);
2407c478bd9Sstevel@tonic-gate static void write_one_file(struct domain_st *);
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate static void lstrcat(char *, const char *);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate /*
2457c478bd9Sstevel@tonic-gate  * Utility functions to malloc a node and initialize fields.
2467c478bd9Sstevel@tonic-gate  */
2477c478bd9Sstevel@tonic-gate static struct domain_st  *new_domain(void);
2487c478bd9Sstevel@tonic-gate static struct strlist_st *new_strlist(void);
2497c478bd9Sstevel@tonic-gate static struct element_st *new_element(void);
2507c478bd9Sstevel@tonic-gate static struct exclude_st *new_exclude(void);
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate /*
2537c478bd9Sstevel@tonic-gate  * Main program of xgettext.
2547c478bd9Sstevel@tonic-gate  */
2557c478bd9Sstevel@tonic-gate int
main(int argc,char ** argv)2567c478bd9Sstevel@tonic-gate main(int argc, char **argv)
2577c478bd9Sstevel@tonic-gate {
2587c478bd9Sstevel@tonic-gate 	int		opterr = FALSE;
2597c478bd9Sstevel@tonic-gate 	int		c;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	initialize_globals();
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "jhax:nsc:d:m:M:p:t")) != EOF) {
2647c478bd9Sstevel@tonic-gate 		switch (c) {
2657c478bd9Sstevel@tonic-gate 		case 'a':
2667c478bd9Sstevel@tonic-gate 			aflg = TRUE;
2677c478bd9Sstevel@tonic-gate 			break;
2687c478bd9Sstevel@tonic-gate 		case 'c':
2697c478bd9Sstevel@tonic-gate 			cflg = TRUE;
2707c478bd9Sstevel@tonic-gate 			comment_tag = optarg;
2717c478bd9Sstevel@tonic-gate 			break;
2727c478bd9Sstevel@tonic-gate 		case 'd':
2737c478bd9Sstevel@tonic-gate 			default_domain = optarg;
2747c478bd9Sstevel@tonic-gate 			break;
2757c478bd9Sstevel@tonic-gate 		case 'h':
2767c478bd9Sstevel@tonic-gate 			hflg = TRUE;
2777c478bd9Sstevel@tonic-gate 			break;
2787c478bd9Sstevel@tonic-gate 		case 'j':
2797c478bd9Sstevel@tonic-gate 			jflg = TRUE;
2807c478bd9Sstevel@tonic-gate 			break;
2817c478bd9Sstevel@tonic-gate 		case 'M':
2827c478bd9Sstevel@tonic-gate 			Mflg = TRUE;
2837c478bd9Sstevel@tonic-gate 			suffix = optarg;
2847c478bd9Sstevel@tonic-gate 			break;
2857c478bd9Sstevel@tonic-gate 		case 'm':
2867c478bd9Sstevel@tonic-gate 			mflg = TRUE;
2877c478bd9Sstevel@tonic-gate 			prefix = optarg;
2887c478bd9Sstevel@tonic-gate 			break;
2897c478bd9Sstevel@tonic-gate 		case 'n':
2907c478bd9Sstevel@tonic-gate 			nflg = TRUE;
2917c478bd9Sstevel@tonic-gate 			break;
2927c478bd9Sstevel@tonic-gate 		case 'p':
2937c478bd9Sstevel@tonic-gate 			pflg = TRUE;
2947c478bd9Sstevel@tonic-gate 			pathname = optarg;
2957c478bd9Sstevel@tonic-gate 			break;
2967c478bd9Sstevel@tonic-gate 		case 's':
2977c478bd9Sstevel@tonic-gate 			sflg = TRUE;
2987c478bd9Sstevel@tonic-gate 			break;
2997c478bd9Sstevel@tonic-gate 		case 't':
3007c478bd9Sstevel@tonic-gate 			tflg = TRUE;
3017c478bd9Sstevel@tonic-gate 			break;
3027c478bd9Sstevel@tonic-gate 		case 'x':
3037c478bd9Sstevel@tonic-gate 			xflg = TRUE;
3047c478bd9Sstevel@tonic-gate 			exclude_file = optarg;
3057c478bd9Sstevel@tonic-gate 			break;
3067c478bd9Sstevel@tonic-gate 		case '?':
3077c478bd9Sstevel@tonic-gate 			opterr = TRUE;
3087c478bd9Sstevel@tonic-gate 			break;
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	/* if -h is used, ignore all other options. */
3137c478bd9Sstevel@tonic-gate 	if (hflg == TRUE) {
3147c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, USAGE);
3157c478bd9Sstevel@tonic-gate 		print_help();
3167c478bd9Sstevel@tonic-gate 		exit(0);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	/* -x can be used only with -a */
3207c478bd9Sstevel@tonic-gate 	if ((xflg == TRUE) && (aflg == FALSE))
3217c478bd9Sstevel@tonic-gate 		opterr = TRUE;
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 	/* -j cannot be used with -a */
3247c478bd9Sstevel@tonic-gate 	if ((jflg == TRUE) && (aflg == TRUE)) {
3257c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3267c478bd9Sstevel@tonic-gate 		"-a and -j options cannot be used together.\n");
3277c478bd9Sstevel@tonic-gate 		opterr = TRUE;
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/* -j cannot be used with -s */
3317c478bd9Sstevel@tonic-gate 	if ((jflg == TRUE) && (sflg == TRUE)) {
3327c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
3337c478bd9Sstevel@tonic-gate 		"-j and -s options cannot be used together.\n");
3347c478bd9Sstevel@tonic-gate 		opterr = TRUE;
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	if (opterr == TRUE) {
3387c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, USAGE);
3397c478bd9Sstevel@tonic-gate 		exit(2);
3407c478bd9Sstevel@tonic-gate 	}
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	/* error, if no files are specified. */
3437c478bd9Sstevel@tonic-gate 	if (optind == argc) {
3447c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, USAGE);
3457c478bd9Sstevel@tonic-gate 		exit(2);
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	if (xflg == TRUE) {
3497c478bd9Sstevel@tonic-gate 		read_exclude_file();
3507c478bd9Sstevel@tonic-gate 	}
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* If files are -, then read from stdin */
3537c478bd9Sstevel@tonic-gate 	if (argv[optind][0] == '-') {
3547c478bd9Sstevel@tonic-gate 		stdin_only = TRUE;
3557c478bd9Sstevel@tonic-gate 		optind++;
3567c478bd9Sstevel@tonic-gate 	} else {
3577c478bd9Sstevel@tonic-gate 		stdin_only = FALSE;
3587c478bd9Sstevel@tonic-gate 	}
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	/* Store argc and argv to pass to yylex() */
3617c478bd9Sstevel@tonic-gate 	gargc = argc;
3627c478bd9Sstevel@tonic-gate 	gargv = argv;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate #ifdef DEBUG
3657c478bd9Sstevel@tonic-gate 	(void) printf("optind=%d\n", optind);
3667c478bd9Sstevel@tonic-gate 	{
3677c478bd9Sstevel@tonic-gate 	int i = optind;
3687c478bd9Sstevel@tonic-gate 	for (; i < argc; i++) {
3697c478bd9Sstevel@tonic-gate 		(void) printf("   %d, <%s>\n", i, argv[i]);
3707c478bd9Sstevel@tonic-gate 	}
3717c478bd9Sstevel@tonic-gate 	}
3727c478bd9Sstevel@tonic-gate #endif
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	if (stdin_only == FALSE) {
3757c478bd9Sstevel@tonic-gate 		if (freopen(argv[optind], "r", stdin) == NULL) {
3767c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
3777c478bd9Sstevel@tonic-gate 			"ERROR, can't open input file: %s\n", argv[optind]);
3787c478bd9Sstevel@tonic-gate 			exit(2);
3797c478bd9Sstevel@tonic-gate 		}
3807c478bd9Sstevel@tonic-gate 		(void) strcpy(curr_file, gargv[optind]);
3817c478bd9Sstevel@tonic-gate 		optind++;
3827c478bd9Sstevel@tonic-gate 	}
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate 	/*
3857c478bd9Sstevel@tonic-gate 	 * Process input.
3867c478bd9Sstevel@tonic-gate 	 */
3877c478bd9Sstevel@tonic-gate 	(void) yylex();
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate #ifdef DEBUG
3907c478bd9Sstevel@tonic-gate 	printf("\n======= default_domain ========\n");
3917c478bd9Sstevel@tonic-gate 	print_one_domain(def_dom);
3927c478bd9Sstevel@tonic-gate 	printf("======= domain list ========\n");
3937c478bd9Sstevel@tonic-gate 	print_all_domain(dom_head);
3947c478bd9Sstevel@tonic-gate #endif
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	/*
3977c478bd9Sstevel@tonic-gate 	 * Write out all .po files.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	write_all_files();
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	return (0);
4027c478bd9Sstevel@tonic-gate } /* main */
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /*
4057c478bd9Sstevel@tonic-gate  * Prints help information for each option.
4067c478bd9Sstevel@tonic-gate  */
4077c478bd9Sstevel@tonic-gate static void
print_help(void)4087c478bd9Sstevel@tonic-gate print_help(void)
4097c478bd9Sstevel@tonic-gate {
4107c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "\n");
411*df69b316SToomas Soome 	(void) fprintf(stderr, "-a\t\t\tfind ALL strings\n");
4127c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
413*df69b316SToomas Soome 	    "-c <comment-tag>\tget comments containing <flag>\n");
4147c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
415*df69b316SToomas Soome 	    "-d <default-domain>\tuse <default-domain> for default domain\n");
416*df69b316SToomas Soome 	(void) fprintf(stderr, "-h\t\t\tHelp\n");
4177c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
418*df69b316SToomas Soome 	    "-j\t\t\tupdate existing file with the current result\n");
4197c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
420*df69b316SToomas Soome 	    "-M <suffix>\t\tfill in msgstr with msgid<suffix>\n");
4217c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
422*df69b316SToomas Soome 	    "-m <prefix>\t\tfill in msgstr with <prefix>msgid\n");
4237c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
424*df69b316SToomas Soome 	    "-n\t\t\tline# file name and line number info in output\n");
4257c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
426*df69b316SToomas Soome 	    "-p <pathname>\t\tuse <pathname> for output file directory\n");
4277c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
428*df69b316SToomas Soome 	    "-s\t\t\tgenerate sorted output files\n");
429*df69b316SToomas Soome 	(void) fprintf(stderr, "-x <exclude-file>\texclude strings in file "
430*df69b316SToomas Soome 	    "<exclude-file> from output\n");
4317c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
432*df69b316SToomas Soome 	    "-\t\t\tread stdin, use as a filter (input only)\n");
4337c478bd9Sstevel@tonic-gate } /* print_help */
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate /*
4367c478bd9Sstevel@tonic-gate  * Extract file name and line number information from macro line
4377c478bd9Sstevel@tonic-gate  * and set the global variable accordingly.
4387c478bd9Sstevel@tonic-gate  * The valid line format is
4397c478bd9Sstevel@tonic-gate  *   1) # nnn
4407c478bd9Sstevel@tonic-gate  *    or
4417c478bd9Sstevel@tonic-gate  *   2) # nnn "xxxxx"
4427c478bd9Sstevel@tonic-gate  *   where nnn is line number and xxxxx is file name.
4437c478bd9Sstevel@tonic-gate  */
4447c478bd9Sstevel@tonic-gate static void
extract_filename_linenumber(char * mline)4457c478bd9Sstevel@tonic-gate extract_filename_linenumber(char *mline)
4467c478bd9Sstevel@tonic-gate {
4477c478bd9Sstevel@tonic-gate 	int	num;
4487c478bd9Sstevel@tonic-gate 	char	*p, *q, *r;
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	/*
4517c478bd9Sstevel@tonic-gate 	 * mline can contain multi newline.
4527c478bd9Sstevel@tonic-gate 	 * line number should be increased by the number of newlines.
4537c478bd9Sstevel@tonic-gate 	 */
4547c478bd9Sstevel@tonic-gate 	p = mline;
4557c478bd9Sstevel@tonic-gate 	while ((p = strchr(p, '\n')) != NULL) {
4567c478bd9Sstevel@tonic-gate 		p++;
4577c478bd9Sstevel@tonic-gate 		curr_linenum++;
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 	p = strchr(mline, ' ');
4607c478bd9Sstevel@tonic-gate 	if (p == NULL)
4617c478bd9Sstevel@tonic-gate 		return;
4627c478bd9Sstevel@tonic-gate 	q = strchr(++p, ' ');
4637c478bd9Sstevel@tonic-gate 	if (q == NULL) {
4647c478bd9Sstevel@tonic-gate 		/* case 1 */
4657c478bd9Sstevel@tonic-gate 		if ((num = atoi(p)) > 0) {
4667c478bd9Sstevel@tonic-gate 			curr_linenum = num;
4677c478bd9Sstevel@tonic-gate 			return;
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate 	} else {
4707c478bd9Sstevel@tonic-gate 		/* case 2 */
4717c478bd9Sstevel@tonic-gate 		*q++ = 0;
4727c478bd9Sstevel@tonic-gate 		if (*q == '"') {
4737c478bd9Sstevel@tonic-gate 			q++;
4747c478bd9Sstevel@tonic-gate 			r = strchr(q, '"');
4757c478bd9Sstevel@tonic-gate 			if (r == NULL) {
4767c478bd9Sstevel@tonic-gate 				return;
4777c478bd9Sstevel@tonic-gate 			}
4787c478bd9Sstevel@tonic-gate 			*r = 0;
4797c478bd9Sstevel@tonic-gate 			if ((num = atoi(p)) > 0) {
4807c478bd9Sstevel@tonic-gate 				curr_linenum = num;
4817c478bd9Sstevel@tonic-gate 				(void) strcpy(curr_file, q);
4827c478bd9Sstevel@tonic-gate 			}
4837c478bd9Sstevel@tonic-gate 		}
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate } /* extract_filename_linenumber */
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate /*
4887c478bd9Sstevel@tonic-gate  * Handler for MACRO line which starts with #.
4897c478bd9Sstevel@tonic-gate  */
4907c478bd9Sstevel@tonic-gate void
handle_macro_line(void)4917c478bd9Sstevel@tonic-gate handle_macro_line(void)
4927c478bd9Sstevel@tonic-gate {
4937c478bd9Sstevel@tonic-gate #ifdef DEBUG
4947c478bd9Sstevel@tonic-gate 	(void) printf("Macro line=<%s>\n", yytext);
4957c478bd9Sstevel@tonic-gate #endif
4967c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
4977c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
5007c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
5017c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
5027c478bd9Sstevel@tonic-gate 		extract_filename_linenumber(yytext);
5037c478bd9Sstevel@tonic-gate 	}
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	curr_linenum--;
5067c478bd9Sstevel@tonic-gate 	handle_newline();
5077c478bd9Sstevel@tonic-gate } /* handle_macro_line */
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate /*
5107c478bd9Sstevel@tonic-gate  * Handler for C++ comments which starts with //.
5117c478bd9Sstevel@tonic-gate  */
5127c478bd9Sstevel@tonic-gate void
handle_cplus_comment_line(void)5137c478bd9Sstevel@tonic-gate handle_cplus_comment_line(void)
5147c478bd9Sstevel@tonic-gate {
5157c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
5167c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
5197c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
5207c478bd9Sstevel@tonic-gate 	} else if ((in_comment == FALSE) &&
521*df69b316SToomas Soome 	    (in_skippable_string == FALSE)) {
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 		/*
5247c478bd9Sstevel@tonic-gate 		 * If already in c comments, don't do anything.
5257c478bd9Sstevel@tonic-gate 		 * Set both flags to TRUE here.
5267c478bd9Sstevel@tonic-gate 		 * Both flags will be set to FALSE when newline
5277c478bd9Sstevel@tonic-gate 		 * encounters.
5287c478bd9Sstevel@tonic-gate 		 */
5297c478bd9Sstevel@tonic-gate 		in_cplus_comment = TRUE;
5307c478bd9Sstevel@tonic-gate 		in_comment = TRUE;
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate } /* handle_cplus_comment_line */
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate  * Handler for the comment start (slash asterisk) in input file.
5367c478bd9Sstevel@tonic-gate  */
5377c478bd9Sstevel@tonic-gate void
handle_open_comment(void)5387c478bd9Sstevel@tonic-gate handle_open_comment(void)
5397c478bd9Sstevel@tonic-gate {
5407c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
5417c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
5447c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
5457c478bd9Sstevel@tonic-gate 	} else if ((in_comment == FALSE) &&
546*df69b316SToomas Soome 	    (in_skippable_string == FALSE)) {
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		in_comment = TRUE;
5497c478bd9Sstevel@tonic-gate 		is_last_comment_line = FALSE;
5507c478bd9Sstevel@tonic-gate 		/*
5517c478bd9Sstevel@tonic-gate 		 * If there is any comment extracted before accidently,
5527c478bd9Sstevel@tonic-gate 		 * clean it up and start the new comment again.
5537c478bd9Sstevel@tonic-gate 		 */
5547c478bd9Sstevel@tonic-gate 		free_strlist(commhead);
5557c478bd9Sstevel@tonic-gate 		commhead = commtail = NULL;
5567c478bd9Sstevel@tonic-gate 	}
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate /*
5607c478bd9Sstevel@tonic-gate  * Handler for the comment end (asterisk slash) in input file.
5617c478bd9Sstevel@tonic-gate  */
5627c478bd9Sstevel@tonic-gate void
handle_close_comment(void)5637c478bd9Sstevel@tonic-gate handle_close_comment(void)
5647c478bd9Sstevel@tonic-gate {
5657c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
5667c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
5677c478bd9Sstevel@tonic-gate 
5687c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
5697c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
5707c478bd9Sstevel@tonic-gate 	} else if (in_skippable_string == FALSE) {
5717c478bd9Sstevel@tonic-gate 		in_comment = FALSE;
5727c478bd9Sstevel@tonic-gate 		is_last_comment_line = TRUE;
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate  * Handler for "gettext" in input file.
5787c478bd9Sstevel@tonic-gate  */
5797c478bd9Sstevel@tonic-gate void
handle_gettext(void)5807c478bd9Sstevel@tonic-gate handle_gettext(void)
5817c478bd9Sstevel@tonic-gate {
5827c478bd9Sstevel@tonic-gate 	/*
5837c478bd9Sstevel@tonic-gate 	 * If -t option is specified to extrct dcgettext,
5847c478bd9Sstevel@tonic-gate 	 * don't do anything for gettext().
5857c478bd9Sstevel@tonic-gate 	 */
5867c478bd9Sstevel@tonic-gate 	if (tflg == TRUE) {
5877c478bd9Sstevel@tonic-gate 		return;
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	num_nested_open_paren = 0;
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
5937c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
5967c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
5977c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
5987c478bd9Sstevel@tonic-gate 		in_gettext = TRUE;
5997c478bd9Sstevel@tonic-gate 		linenum_saved = curr_linenum;
6007c478bd9Sstevel@tonic-gate 		/*
6017c478bd9Sstevel@tonic-gate 		 * gettext will be put into default domain .po file
6027c478bd9Sstevel@tonic-gate 		 * curr_domain does not change for gettext.
6037c478bd9Sstevel@tonic-gate 		 */
604*df69b316SToomas Soome 		curr_domain[0] = '\0';
6057c478bd9Sstevel@tonic-gate 	}
6067c478bd9Sstevel@tonic-gate } /* handle_gettext */
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate /*
6097c478bd9Sstevel@tonic-gate  * Handler for "dgettext" in input file.
6107c478bd9Sstevel@tonic-gate  */
6117c478bd9Sstevel@tonic-gate void
handle_dgettext(void)6127c478bd9Sstevel@tonic-gate handle_dgettext(void)
6137c478bd9Sstevel@tonic-gate {
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * If -t option is specified to extrct dcgettext,
6167c478bd9Sstevel@tonic-gate 	 * don't do anything for dgettext().
6177c478bd9Sstevel@tonic-gate 	 */
6187c478bd9Sstevel@tonic-gate 	if (tflg == TRUE) {
6197c478bd9Sstevel@tonic-gate 		return;
6207c478bd9Sstevel@tonic-gate 	}
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 	num_nested_open_paren = 0;
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
6257c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
6287c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
6297c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
6307c478bd9Sstevel@tonic-gate 		in_dgettext = TRUE;
6317c478bd9Sstevel@tonic-gate 		linenum_saved = curr_linenum;
6327c478bd9Sstevel@tonic-gate 		/*
6337c478bd9Sstevel@tonic-gate 		 * dgettext will be put into domain file specified.
6347c478bd9Sstevel@tonic-gate 		 * curr_domain will follow.
6357c478bd9Sstevel@tonic-gate 		 */
636*df69b316SToomas Soome 		curr_domain[0] = '\0';
6377c478bd9Sstevel@tonic-gate 	}
6387c478bd9Sstevel@tonic-gate } /* handle_dgettext */
6397c478bd9Sstevel@tonic-gate 
6407c478bd9Sstevel@tonic-gate /*
6417c478bd9Sstevel@tonic-gate  * Handler for "dcgettext" in input file.
6427c478bd9Sstevel@tonic-gate  */
6437c478bd9Sstevel@tonic-gate void
handle_dcgettext(void)6447c478bd9Sstevel@tonic-gate handle_dcgettext(void)
6457c478bd9Sstevel@tonic-gate {
6467c478bd9Sstevel@tonic-gate 	/*
6477c478bd9Sstevel@tonic-gate 	 * dcgettext will be extracted only when -t flag is specified.
6487c478bd9Sstevel@tonic-gate 	 */
6497c478bd9Sstevel@tonic-gate 	if (tflg == FALSE) {
6507c478bd9Sstevel@tonic-gate 		return;
6517c478bd9Sstevel@tonic-gate 	}
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 	num_nested_open_paren = 0;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 	is_first_comma_found = FALSE;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
6587c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
6617c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
6627c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
6637c478bd9Sstevel@tonic-gate 		in_dcgettext = TRUE;
6647c478bd9Sstevel@tonic-gate 		linenum_saved = curr_linenum;
6657c478bd9Sstevel@tonic-gate 		/*
6667c478bd9Sstevel@tonic-gate 		 * dcgettext will be put into domain file specified.
6677c478bd9Sstevel@tonic-gate 		 * curr_domain will follow.
6687c478bd9Sstevel@tonic-gate 		 */
669*df69b316SToomas Soome 		curr_domain[0] = '\0';
6707c478bd9Sstevel@tonic-gate 	}
6717c478bd9Sstevel@tonic-gate } /* handle_dcgettext */
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate /*
6747c478bd9Sstevel@tonic-gate  * Handler for "textdomain" in input file.
6757c478bd9Sstevel@tonic-gate  */
6767c478bd9Sstevel@tonic-gate void
handle_textdomain(void)6777c478bd9Sstevel@tonic-gate handle_textdomain(void)
6787c478bd9Sstevel@tonic-gate {
6797c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
6807c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
6837c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
6847c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
6857c478bd9Sstevel@tonic-gate 		in_textdomain = TRUE;
6867c478bd9Sstevel@tonic-gate 		linenum_saved = curr_linenum;
687*df69b316SToomas Soome 		curr_domain[0] = '\0';
6887c478bd9Sstevel@tonic-gate 	}
6897c478bd9Sstevel@tonic-gate } /* handle_textdomain */
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate  * Handler for '(' in input file.
6937c478bd9Sstevel@tonic-gate  */
6947c478bd9Sstevel@tonic-gate void
handle_open_paren(void)6957c478bd9Sstevel@tonic-gate handle_open_paren(void)
6967c478bd9Sstevel@tonic-gate {
6977c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
6987c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
7017c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
7027c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
7037c478bd9Sstevel@tonic-gate 		if ((in_gettext == TRUE) ||
7047c478bd9Sstevel@tonic-gate 		    (in_dgettext == TRUE) ||
7057c478bd9Sstevel@tonic-gate 		    (in_dcgettext == TRUE) ||
7067c478bd9Sstevel@tonic-gate 		    (in_textdomain == TRUE)) {
7077c478bd9Sstevel@tonic-gate 			in_str = TRUE;
7087c478bd9Sstevel@tonic-gate 			num_nested_open_paren++;
7097c478bd9Sstevel@tonic-gate 		}
7107c478bd9Sstevel@tonic-gate 	}
7117c478bd9Sstevel@tonic-gate } /* handle_open_paren */
7127c478bd9Sstevel@tonic-gate 
7137c478bd9Sstevel@tonic-gate /*
7147c478bd9Sstevel@tonic-gate  * Handler for ')' in input file.
7157c478bd9Sstevel@tonic-gate  */
7167c478bd9Sstevel@tonic-gate void
handle_close_paren(void)7177c478bd9Sstevel@tonic-gate handle_close_paren(void)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
7207c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
7237c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
7247c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
7257c478bd9Sstevel@tonic-gate 		if ((in_gettext == TRUE) ||
7267c478bd9Sstevel@tonic-gate 		    (in_dgettext == TRUE) ||
7277c478bd9Sstevel@tonic-gate 		    (in_dcgettext == TRUE) ||
7287c478bd9Sstevel@tonic-gate 		    (in_textdomain == TRUE)) {
7297c478bd9Sstevel@tonic-gate 			/*
7307c478bd9Sstevel@tonic-gate 			 * If this is not the matching close paren with
7317c478bd9Sstevel@tonic-gate 			 * the first open paren, no action is necessary.
7327c478bd9Sstevel@tonic-gate 			 */
7337c478bd9Sstevel@tonic-gate 			if (--num_nested_open_paren > 0)
7347c478bd9Sstevel@tonic-gate 				return;
7357c478bd9Sstevel@tonic-gate 			add_str_to_element_list(in_textdomain, curr_domain);
7367c478bd9Sstevel@tonic-gate 			in_str = FALSE;
7377c478bd9Sstevel@tonic-gate 			in_gettext = FALSE;
7387c478bd9Sstevel@tonic-gate 			in_dgettext = FALSE;
7397c478bd9Sstevel@tonic-gate 			in_dcgettext = FALSE;
7407c478bd9Sstevel@tonic-gate 			in_textdomain = FALSE;
7417c478bd9Sstevel@tonic-gate 		} else if (aflg == TRUE) {
7427c478bd9Sstevel@tonic-gate 			end_ansi_string();
7437c478bd9Sstevel@tonic-gate 		}
7447c478bd9Sstevel@tonic-gate 	}
7457c478bd9Sstevel@tonic-gate } /* handle_close_paren */
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate /*
7487c478bd9Sstevel@tonic-gate  * Handler for '\\n' in input file.
7497c478bd9Sstevel@tonic-gate  *
7507c478bd9Sstevel@tonic-gate  * This is a '\' followed by new line.
7517c478bd9Sstevel@tonic-gate  * This can be treated like a new line except when this is a continuation
7527c478bd9Sstevel@tonic-gate  * of a ANSI-C string.
7537c478bd9Sstevel@tonic-gate  * If this is a part of ANSI string, treat the current line as a double
7547c478bd9Sstevel@tonic-gate  * quoted string and the next line is the start of the double quoted
7557c478bd9Sstevel@tonic-gate  * string.
7567c478bd9Sstevel@tonic-gate  */
7577c478bd9Sstevel@tonic-gate void
handle_esc_newline(void)7587c478bd9Sstevel@tonic-gate handle_esc_newline(void)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
7617c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, "\\");
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	curr_linenum++;
7647c478bd9Sstevel@tonic-gate 
7657c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
7667c478bd9Sstevel@tonic-gate 		add_qstring_to_str();
7677c478bd9Sstevel@tonic-gate 	} else if ((in_comment == TRUE) ||
7687c478bd9Sstevel@tonic-gate 	    (is_last_comment_line == TRUE)) {
7697c478bd9Sstevel@tonic-gate 		if (in_cplus_comment == FALSE) {
7707c478bd9Sstevel@tonic-gate 			add_line_to_comment();
7717c478bd9Sstevel@tonic-gate 		}
7727c478bd9Sstevel@tonic-gate 	}
7737c478bd9Sstevel@tonic-gate 
774*df69b316SToomas Soome 	curr_line[0] = '\0';
7757c478bd9Sstevel@tonic-gate } /* handle_esc_newline */
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate  * Handler for '"' in input file.
7797c478bd9Sstevel@tonic-gate  */
7807c478bd9Sstevel@tonic-gate void
handle_quote(void)7817c478bd9Sstevel@tonic-gate handle_quote(void)
7827c478bd9Sstevel@tonic-gate {
7837c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
7847c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
7857c478bd9Sstevel@tonic-gate 
7867c478bd9Sstevel@tonic-gate 	if (in_comment == TRUE) {
7877c478bd9Sstevel@tonic-gate 		/*EMPTY*/
7887c478bd9Sstevel@tonic-gate 	} else if ((in_gettext == TRUE) ||
789*df69b316SToomas Soome 	    (in_dgettext == TRUE) ||
790*df69b316SToomas Soome 	    (in_dcgettext == TRUE) ||
791*df69b316SToomas Soome 	    (in_textdomain == TRUE)) {
7927c478bd9Sstevel@tonic-gate 		if (in_str == TRUE) {
7937c478bd9Sstevel@tonic-gate 			if (in_quote == FALSE) {
7947c478bd9Sstevel@tonic-gate 				in_quote = TRUE;
7957c478bd9Sstevel@tonic-gate 			} else {
7967c478bd9Sstevel@tonic-gate 				add_qstring_to_str();
7977c478bd9Sstevel@tonic-gate 				in_quote = FALSE;
7987c478bd9Sstevel@tonic-gate 			}
7997c478bd9Sstevel@tonic-gate 		}
8007c478bd9Sstevel@tonic-gate 	} else if (aflg == TRUE) {
8017c478bd9Sstevel@tonic-gate 		/*
8027c478bd9Sstevel@tonic-gate 		 * The quote is found outside of gettext, dgetext, and
8037c478bd9Sstevel@tonic-gate 		 * textdomain. Everytime a quoted string is found,
8047c478bd9Sstevel@tonic-gate 		 * add it to the string list.
8057c478bd9Sstevel@tonic-gate 		 * in_str stays TRUE until ANSI string ends.
8067c478bd9Sstevel@tonic-gate 		 */
8077c478bd9Sstevel@tonic-gate 		if (in_str == TRUE) {
8087c478bd9Sstevel@tonic-gate 			if (in_quote == TRUE) {
8097c478bd9Sstevel@tonic-gate 				in_quote = FALSE;
8107c478bd9Sstevel@tonic-gate 				add_qstring_to_str();
8117c478bd9Sstevel@tonic-gate 			} else {
8127c478bd9Sstevel@tonic-gate 				in_quote = TRUE;
8137c478bd9Sstevel@tonic-gate 			}
8147c478bd9Sstevel@tonic-gate 		} else {
8157c478bd9Sstevel@tonic-gate 			in_str = TRUE;
8167c478bd9Sstevel@tonic-gate 			in_quote = TRUE;
8177c478bd9Sstevel@tonic-gate 			linenum_saved = curr_linenum;
8187c478bd9Sstevel@tonic-gate 		}
8197c478bd9Sstevel@tonic-gate 	} else {
8207c478bd9Sstevel@tonic-gate 		in_skippable_string = (in_skippable_string == TRUE) ?
821*df69b316SToomas Soome 		    FALSE : TRUE;
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate } /* handle_quote */
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate /*
8267c478bd9Sstevel@tonic-gate  * Handler for ' ' or TAB in input file.
8277c478bd9Sstevel@tonic-gate  */
8287c478bd9Sstevel@tonic-gate void
handle_spaces(void)8297c478bd9Sstevel@tonic-gate handle_spaces(void)
8307c478bd9Sstevel@tonic-gate {
8317c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
8327c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
8357c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
8367c478bd9Sstevel@tonic-gate 	}
8377c478bd9Sstevel@tonic-gate } /* handle_spaces */
8387c478bd9Sstevel@tonic-gate 
8397c478bd9Sstevel@tonic-gate /*
8407c478bd9Sstevel@tonic-gate  * Flattens a linked list containing ANSI string to the one string.
8417c478bd9Sstevel@tonic-gate  */
8427c478bd9Sstevel@tonic-gate static void
copy_strlist_to_str(char * str,struct strlist_st * strlist)8437c478bd9Sstevel@tonic-gate copy_strlist_to_str(char *str, struct strlist_st *strlist)
8447c478bd9Sstevel@tonic-gate {
8457c478bd9Sstevel@tonic-gate 	struct strlist_st	*p;
8467c478bd9Sstevel@tonic-gate 
847*df69b316SToomas Soome 	str[0] = '\0';
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	if (strlist != NULL) {
8507c478bd9Sstevel@tonic-gate 		p = strlist;
8517c478bd9Sstevel@tonic-gate 		while (p != NULL) {
8527c478bd9Sstevel@tonic-gate 			if (p->str != NULL) {
8537c478bd9Sstevel@tonic-gate 				lstrcat(str, p->str);
8547c478bd9Sstevel@tonic-gate 			}
8557c478bd9Sstevel@tonic-gate 			p = p->next;
8567c478bd9Sstevel@tonic-gate 		}
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate } /* copy_strlist_to_str */
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate /*
8617c478bd9Sstevel@tonic-gate  * Handler for ',' in input file.
8627c478bd9Sstevel@tonic-gate  */
8637c478bd9Sstevel@tonic-gate void
handle_comma(void)8647c478bd9Sstevel@tonic-gate handle_comma(void)
8657c478bd9Sstevel@tonic-gate {
8667c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
8677c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
8707c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
8717c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
8727c478bd9Sstevel@tonic-gate 		if (in_str == TRUE) {
8737c478bd9Sstevel@tonic-gate 			if (in_dgettext == TRUE) {
8747c478bd9Sstevel@tonic-gate 				copy_strlist_to_str(curr_domain, strhead);
8757c478bd9Sstevel@tonic-gate 				free_strlist(strhead);
8767c478bd9Sstevel@tonic-gate 				strhead = strtail = NULL;
8777c478bd9Sstevel@tonic-gate 			} else if (in_dcgettext == TRUE) {
8787c478bd9Sstevel@tonic-gate 				/*
8797c478bd9Sstevel@tonic-gate 				 * Ignore the second comma.
8807c478bd9Sstevel@tonic-gate 				 */
8817c478bd9Sstevel@tonic-gate 				if (is_first_comma_found == FALSE) {
8827c478bd9Sstevel@tonic-gate 					copy_strlist_to_str(curr_domain,
883*df69b316SToomas Soome 					    strhead);
8847c478bd9Sstevel@tonic-gate 					free_strlist(strhead);
8857c478bd9Sstevel@tonic-gate 					strhead = strtail = NULL;
8867c478bd9Sstevel@tonic-gate 					is_first_comma_found = TRUE;
8877c478bd9Sstevel@tonic-gate 				}
8887c478bd9Sstevel@tonic-gate 			} else if (aflg == TRUE) {
8897c478bd9Sstevel@tonic-gate 				end_ansi_string();
8907c478bd9Sstevel@tonic-gate 			}
8917c478bd9Sstevel@tonic-gate 		}
8927c478bd9Sstevel@tonic-gate 	}
8937c478bd9Sstevel@tonic-gate } /* handle_comma */
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate /*
8967c478bd9Sstevel@tonic-gate  * Handler for any other character that does not have special handler.
8977c478bd9Sstevel@tonic-gate  */
8987c478bd9Sstevel@tonic-gate void
handle_character(void)8997c478bd9Sstevel@tonic-gate handle_character(void)
9007c478bd9Sstevel@tonic-gate {
9017c478bd9Sstevel@tonic-gate 	if (cflg == TRUE)
9027c478bd9Sstevel@tonic-gate 		lstrcat(curr_line, yytext);
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if (in_quote == TRUE) {
9057c478bd9Sstevel@tonic-gate 		lstrcat(qstring_buf, yytext);
9067c478bd9Sstevel@tonic-gate 	} else if (in_comment == FALSE) {
9077c478bd9Sstevel@tonic-gate 		if (in_str == TRUE) {
9087c478bd9Sstevel@tonic-gate 			if (aflg == TRUE) {
9097c478bd9Sstevel@tonic-gate 				end_ansi_string();
9107c478bd9Sstevel@tonic-gate 			}
9117c478bd9Sstevel@tonic-gate 		}
9127c478bd9Sstevel@tonic-gate 	}
9137c478bd9Sstevel@tonic-gate } /* handle_character */
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate /*
9167c478bd9Sstevel@tonic-gate  * Handler for new line in input file.
9177c478bd9Sstevel@tonic-gate  */
9187c478bd9Sstevel@tonic-gate void
handle_newline(void)9197c478bd9Sstevel@tonic-gate handle_newline(void)
9207c478bd9Sstevel@tonic-gate {
9217c478bd9Sstevel@tonic-gate 	curr_linenum++;
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 	/*
9247c478bd9Sstevel@tonic-gate 	 * in_quote is always FALSE here for ANSI-C code.
9257c478bd9Sstevel@tonic-gate 	 */
9267c478bd9Sstevel@tonic-gate 	if ((in_comment == TRUE) ||
9277c478bd9Sstevel@tonic-gate 	    (is_last_comment_line == TRUE)) {
9287c478bd9Sstevel@tonic-gate 		if (in_cplus_comment == TRUE) {
9297c478bd9Sstevel@tonic-gate 			in_cplus_comment = FALSE;
9307c478bd9Sstevel@tonic-gate 			in_comment = FALSE;
9317c478bd9Sstevel@tonic-gate 		} else {
9327c478bd9Sstevel@tonic-gate 			add_line_to_comment();
9337c478bd9Sstevel@tonic-gate 		}
9347c478bd9Sstevel@tonic-gate 	}
9357c478bd9Sstevel@tonic-gate 
936*df69b316SToomas Soome 	curr_line[0] = '\0';
9377c478bd9Sstevel@tonic-gate 	/*
9387c478bd9Sstevel@tonic-gate 	 * C++ comment always ends with new line.
9397c478bd9Sstevel@tonic-gate 	 */
9407c478bd9Sstevel@tonic-gate } /* handle_newline */
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate /*
9437c478bd9Sstevel@tonic-gate  * Process ANSI string.
9447c478bd9Sstevel@tonic-gate  */
9457c478bd9Sstevel@tonic-gate static void
end_ansi_string(void)9467c478bd9Sstevel@tonic-gate end_ansi_string(void)
9477c478bd9Sstevel@tonic-gate {
9487c478bd9Sstevel@tonic-gate 	if ((aflg == TRUE) &&
9497c478bd9Sstevel@tonic-gate 	    (in_str == TRUE) &&
9507c478bd9Sstevel@tonic-gate 	    (in_gettext == FALSE) &&
9517c478bd9Sstevel@tonic-gate 	    (in_dgettext == FALSE) &&
9527c478bd9Sstevel@tonic-gate 	    (in_dcgettext == FALSE) &&
9537c478bd9Sstevel@tonic-gate 	    (in_textdomain == FALSE)) {
9547c478bd9Sstevel@tonic-gate 		add_str_to_element_list(FALSE, curr_domain);
9557c478bd9Sstevel@tonic-gate 		in_str = FALSE;
9567c478bd9Sstevel@tonic-gate 	}
9577c478bd9Sstevel@tonic-gate } /* end_ansi_string */
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate /*
9607c478bd9Sstevel@tonic-gate  * Initialize global variables if necessary.
9617c478bd9Sstevel@tonic-gate  */
9627c478bd9Sstevel@tonic-gate static void
initialize_globals(void)9637c478bd9Sstevel@tonic-gate initialize_globals(void)
9647c478bd9Sstevel@tonic-gate {
9657c478bd9Sstevel@tonic-gate 	default_domain = strdup(DEFAULT_DOMAIN);
966*df69b316SToomas Soome 	curr_domain[0] = '\0';
967*df69b316SToomas Soome 	curr_file[0] = '\0';
968*df69b316SToomas Soome 	qstring_buf[0] = '\0';
9697c478bd9Sstevel@tonic-gate } /* initialize_globals() */
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate /*
9727c478bd9Sstevel@tonic-gate  * Extract only string part when read a exclude file by removing
9737c478bd9Sstevel@tonic-gate  * keywords (e.g. msgid, msgstr, # ) and heading and trailing blanks and
9747c478bd9Sstevel@tonic-gate  * double quotes.
9757c478bd9Sstevel@tonic-gate  */
9767c478bd9Sstevel@tonic-gate static void
trim_line(char * line)9777c478bd9Sstevel@tonic-gate trim_line(char *line)
9787c478bd9Sstevel@tonic-gate {
9797c478bd9Sstevel@tonic-gate 	int	i, p, len;
9807c478bd9Sstevel@tonic-gate 	int	first = 0;
9817c478bd9Sstevel@tonic-gate 	int	last = 0;
9827c478bd9Sstevel@tonic-gate 	char	c;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	len = strlen(line);
9857c478bd9Sstevel@tonic-gate 
9867c478bd9Sstevel@tonic-gate 	/*
9877c478bd9Sstevel@tonic-gate 	 * Find the position of the last non-whitespace character.
9887c478bd9Sstevel@tonic-gate 	 */
9897c478bd9Sstevel@tonic-gate 	i = len - 1;
9907c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
9917c478bd9Sstevel@tonic-gate 	while (1) {
9927c478bd9Sstevel@tonic-gate 		c = line[i--];
9937c478bd9Sstevel@tonic-gate 		if ((c != ' ') && (c != '\n') && (c != '\t')) {
9947c478bd9Sstevel@tonic-gate 			last = ++i;
9957c478bd9Sstevel@tonic-gate 			break;
9967c478bd9Sstevel@tonic-gate 		}
9977c478bd9Sstevel@tonic-gate 	}
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate 	/*
10007c478bd9Sstevel@tonic-gate 	 * Find the position of the first non-whitespace character
10017c478bd9Sstevel@tonic-gate 	 * by skipping "msgid" initially.
10027c478bd9Sstevel@tonic-gate 	 */
10037c478bd9Sstevel@tonic-gate 	if (strncmp("msgid ", line, 6) == 0) {
10047c478bd9Sstevel@tonic-gate 		i = 5;
10057c478bd9Sstevel@tonic-gate 	} else if (strncmp("msgstr ", line, 7) == 0) {
10067c478bd9Sstevel@tonic-gate 		i = 6;
10077c478bd9Sstevel@tonic-gate 	} else if (strncmp("# ", line, 2) == 0) {
10087c478bd9Sstevel@tonic-gate 		i = 2;
10097c478bd9Sstevel@tonic-gate 	} else {
10107c478bd9Sstevel@tonic-gate 		i = 0;
10117c478bd9Sstevel@tonic-gate 	}
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
10147c478bd9Sstevel@tonic-gate 	while (1) {
10157c478bd9Sstevel@tonic-gate 		c = line[i++];
10167c478bd9Sstevel@tonic-gate 		if ((c != ' ') && (c != '\n') && (c != '\t')) {
10177c478bd9Sstevel@tonic-gate 			first = --i;
10187c478bd9Sstevel@tonic-gate 			break;
10197c478bd9Sstevel@tonic-gate 		}
10207c478bd9Sstevel@tonic-gate 	}
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate 	/*
10237c478bd9Sstevel@tonic-gate 	 * For Backward compatibility, we consider both double quoted
10247c478bd9Sstevel@tonic-gate 	 * string and non-quoted string.
10257c478bd9Sstevel@tonic-gate 	 * The double quote is removed before being stored if exists.
10267c478bd9Sstevel@tonic-gate 	 */
10277c478bd9Sstevel@tonic-gate 	if (line[first] == '"') {
10287c478bd9Sstevel@tonic-gate 		first++;
10297c478bd9Sstevel@tonic-gate 	}
10307c478bd9Sstevel@tonic-gate 	if (line[last] == '"') {
10317c478bd9Sstevel@tonic-gate 		last--;
10327c478bd9Sstevel@tonic-gate 	}
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	/*
10357c478bd9Sstevel@tonic-gate 	 * Now copy the valid part of the string.
10367c478bd9Sstevel@tonic-gate 	 */
10377c478bd9Sstevel@tonic-gate 	p = first;
10387c478bd9Sstevel@tonic-gate 	for (i = 0; i <= (last-first); i++) {
10397c478bd9Sstevel@tonic-gate 		line[i] = line[p++];
10407c478bd9Sstevel@tonic-gate 	}
1041*df69b316SToomas Soome 	line [i] = '\0';
10427c478bd9Sstevel@tonic-gate } /* trim_line */
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate /*
10457c478bd9Sstevel@tonic-gate  * Read exclude file and stores it in the global linked list.
10467c478bd9Sstevel@tonic-gate  */
10477c478bd9Sstevel@tonic-gate static void
read_exclude_file(void)10487c478bd9Sstevel@tonic-gate read_exclude_file(void)
10497c478bd9Sstevel@tonic-gate {
10507c478bd9Sstevel@tonic-gate 	FILE	*fp;
10517c478bd9Sstevel@tonic-gate 	struct exclude_st	*tmp_excl;
10527c478bd9Sstevel@tonic-gate 	struct strlist_st	*tail;
10537c478bd9Sstevel@tonic-gate 	int			ignore_line;
10547c478bd9Sstevel@tonic-gate 	char			line [MAX_STRING_LEN];
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	if ((fp = fopen(exclude_file, "r")) == NULL) {
10577c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "ERROR, can't open exclude file: %s\n",
1058*df69b316SToomas Soome 		    exclude_file);
10597c478bd9Sstevel@tonic-gate 		exit(2);
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	ignore_line = TRUE;
10637c478bd9Sstevel@tonic-gate 	while (fgets(line, MAX_STRING_LEN, fp) != NULL) {
10647c478bd9Sstevel@tonic-gate 		/*
10657c478bd9Sstevel@tonic-gate 		 * Line starting with # is a comment line and ignored.
10667c478bd9Sstevel@tonic-gate 		 * Blank line is ignored, too.
10677c478bd9Sstevel@tonic-gate 		 */
10687c478bd9Sstevel@tonic-gate 		if ((line[0] == '\n') || (line[0] == '#')) {
10697c478bd9Sstevel@tonic-gate 			continue;
10707c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "msgstr", 6) == 0) {
10717c478bd9Sstevel@tonic-gate 			ignore_line = TRUE;
10727c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "domain", 6) == 0) {
10737c478bd9Sstevel@tonic-gate 			ignore_line = TRUE;
10747c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "msgid", 5) == 0) {
10757c478bd9Sstevel@tonic-gate 			ignore_line = FALSE;
10767c478bd9Sstevel@tonic-gate 			tmp_excl = new_exclude();
10777c478bd9Sstevel@tonic-gate 			tmp_excl->exstr = new_strlist();
10787c478bd9Sstevel@tonic-gate 			trim_line(line);
10797c478bd9Sstevel@tonic-gate 			tmp_excl->exstr->str = strdup(line);
10807c478bd9Sstevel@tonic-gate 			tail = tmp_excl->exstr;
10817c478bd9Sstevel@tonic-gate 			/*
10827c478bd9Sstevel@tonic-gate 			 * Prepend new exclude string node to the list.
10837c478bd9Sstevel@tonic-gate 			 */
10847c478bd9Sstevel@tonic-gate 			tmp_excl->next = excl_head;
10857c478bd9Sstevel@tonic-gate 			excl_head = tmp_excl;
10867c478bd9Sstevel@tonic-gate 		} else {
10877c478bd9Sstevel@tonic-gate 			/*
10887c478bd9Sstevel@tonic-gate 			 * If more than one line of string forms msgid,
10897c478bd9Sstevel@tonic-gate 			 * append it to the string linked list.
10907c478bd9Sstevel@tonic-gate 			 */
10917c478bd9Sstevel@tonic-gate 			if (ignore_line == FALSE) {
10927c478bd9Sstevel@tonic-gate 				trim_line(line);
10937c478bd9Sstevel@tonic-gate 				tail->next = new_strlist();
10947c478bd9Sstevel@tonic-gate 				tail->next->str = strdup(line);
10957c478bd9Sstevel@tonic-gate 				tail = tail->next;
10967c478bd9Sstevel@tonic-gate 			}
10977c478bd9Sstevel@tonic-gate 		}
10987c478bd9Sstevel@tonic-gate 	} /* while */
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate #ifdef DEBUG
11017c478bd9Sstevel@tonic-gate 	tmp_excl = excl_head;
11027c478bd9Sstevel@tonic-gate 	while (tmp_excl != NULL) {
11037c478bd9Sstevel@tonic-gate 		printf("============================\n");
11047c478bd9Sstevel@tonic-gate 		tail = tmp_excl->exstr;
11057c478bd9Sstevel@tonic-gate 		while (tail != NULL) {
11067c478bd9Sstevel@tonic-gate 			printf("%s###\n", tail->str);
11077c478bd9Sstevel@tonic-gate 			tail = tail->next;
11087c478bd9Sstevel@tonic-gate 		}
11097c478bd9Sstevel@tonic-gate 		tmp_excl = tmp_excl->next;
11107c478bd9Sstevel@tonic-gate 	}
11117c478bd9Sstevel@tonic-gate #endif
11127c478bd9Sstevel@tonic-gate } /* read_exclude_file */
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate /*
11157c478bd9Sstevel@tonic-gate  * Get next character from the string list containing ANSI style string.
11167c478bd9Sstevel@tonic-gate  * This function returns three valus. (p, *m, *c).
11177c478bd9Sstevel@tonic-gate  * p is returned by return value and, *m and *c are returned by changing
11187c478bd9Sstevel@tonic-gate  * values in the location pointed.
11197c478bd9Sstevel@tonic-gate  *
11207c478bd9Sstevel@tonic-gate  *  p : points node in the linked list for ANSI string.
11217c478bd9Sstevel@tonic-gate  *	Each node contains double quoted string.
11227c478bd9Sstevel@tonic-gate  *  m : The location of the next characters in the double quoted string
11237c478bd9Sstevel@tonic-gate  *	as integer index in the string.
11247c478bd9Sstevel@tonic-gate  *	When it gets to end of quoted string, the next node will be
11257c478bd9Sstevel@tonic-gate  *	read and m starts as zero for every new node.
11267c478bd9Sstevel@tonic-gate  *  c : Stores the value of the characterto be returned.
11277c478bd9Sstevel@tonic-gate  */
11287c478bd9Sstevel@tonic-gate static struct strlist_st *
get_next_ch(struct strlist_st * p,int * m,char * c)11297c478bd9Sstevel@tonic-gate get_next_ch(struct strlist_st *p, int *m, char *c)
11307c478bd9Sstevel@tonic-gate {
11317c478bd9Sstevel@tonic-gate 	char	ch, oct, hex;
11327c478bd9Sstevel@tonic-gate 	int	value, i;
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 	/*
11357c478bd9Sstevel@tonic-gate 	 * From the string list, find non-null string first.
11367c478bd9Sstevel@tonic-gate 	 */
11377c478bd9Sstevel@tonic-gate 
11387c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
11397c478bd9Sstevel@tonic-gate 	while (1) {
11407c478bd9Sstevel@tonic-gate 		if (p == NULL) {
11417c478bd9Sstevel@tonic-gate 			break;
11427c478bd9Sstevel@tonic-gate 		} else if (p->str == NULL)  {
11437c478bd9Sstevel@tonic-gate 			p = p->next;
1144*df69b316SToomas Soome 		} else if (p->str[*m] == '\0') {
11457c478bd9Sstevel@tonic-gate 			p = p->next;
11467c478bd9Sstevel@tonic-gate 			*m = 0;
11477c478bd9Sstevel@tonic-gate 		} else {
11487c478bd9Sstevel@tonic-gate 			break;
11497c478bd9Sstevel@tonic-gate 		}
11507c478bd9Sstevel@tonic-gate 	}
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 	/*
11537c478bd9Sstevel@tonic-gate 	 * No more character is available.
11547c478bd9Sstevel@tonic-gate 	 */
11557c478bd9Sstevel@tonic-gate 	if (p == NULL) {
11567c478bd9Sstevel@tonic-gate 		*c = 0;
11577c478bd9Sstevel@tonic-gate 		return (NULL);
11587c478bd9Sstevel@tonic-gate 	}
11597c478bd9Sstevel@tonic-gate 
11607c478bd9Sstevel@tonic-gate 	/*
11617c478bd9Sstevel@tonic-gate 	 * Check if the character back slash.
11627c478bd9Sstevel@tonic-gate 	 * If yes, ANSI defined escape sequence rule is used.
11637c478bd9Sstevel@tonic-gate 	 */
11647c478bd9Sstevel@tonic-gate 	if (p->str[*m] != '\\') {
11657c478bd9Sstevel@tonic-gate 		*c = p->str[*m];
11667c478bd9Sstevel@tonic-gate 		*m = *m + 1;
11677c478bd9Sstevel@tonic-gate 		return (p);
11687c478bd9Sstevel@tonic-gate 	} else {
11697c478bd9Sstevel@tonic-gate 		/*
11707c478bd9Sstevel@tonic-gate 		 * Get next character after '\'.
11717c478bd9Sstevel@tonic-gate 		 */
11727c478bd9Sstevel@tonic-gate 		*m = *m + 1;
11737c478bd9Sstevel@tonic-gate 		ch = p->str[*m];
11747c478bd9Sstevel@tonic-gate 		switch (ch) {
11757c478bd9Sstevel@tonic-gate 		case 'a':
11767c478bd9Sstevel@tonic-gate 			*c = '\a';
11777c478bd9Sstevel@tonic-gate 			break;
11787c478bd9Sstevel@tonic-gate 		case 'b':
11797c478bd9Sstevel@tonic-gate 			*c = '\b';
11807c478bd9Sstevel@tonic-gate 			break;
11817c478bd9Sstevel@tonic-gate 		case 'f':
11827c478bd9Sstevel@tonic-gate 			*c = '\f';
11837c478bd9Sstevel@tonic-gate 			break;
11847c478bd9Sstevel@tonic-gate 		case 'n':
11857c478bd9Sstevel@tonic-gate 			*c = '\n';
11867c478bd9Sstevel@tonic-gate 			break;
11877c478bd9Sstevel@tonic-gate 		case 'r':
11887c478bd9Sstevel@tonic-gate 			*c = '\r';
11897c478bd9Sstevel@tonic-gate 			break;
11907c478bd9Sstevel@tonic-gate 		case 't':
11917c478bd9Sstevel@tonic-gate 			*c = '\t';
11927c478bd9Sstevel@tonic-gate 			break;
11937c478bd9Sstevel@tonic-gate 		case 'v':
11947c478bd9Sstevel@tonic-gate 			*c = '\v';
11957c478bd9Sstevel@tonic-gate 			break;
11967c478bd9Sstevel@tonic-gate 		case '0':
11977c478bd9Sstevel@tonic-gate 		case '1':
11987c478bd9Sstevel@tonic-gate 		case '2':
11997c478bd9Sstevel@tonic-gate 		case '3':
12007c478bd9Sstevel@tonic-gate 		case '4':
12017c478bd9Sstevel@tonic-gate 		case '5':
12027c478bd9Sstevel@tonic-gate 		case '6':
12037c478bd9Sstevel@tonic-gate 		case '7':
12047c478bd9Sstevel@tonic-gate 			/*
12057c478bd9Sstevel@tonic-gate 			 * Get maximum of three octal digits.
12067c478bd9Sstevel@tonic-gate 			 */
12077c478bd9Sstevel@tonic-gate 			value = ch;
12087c478bd9Sstevel@tonic-gate 			for (i = 0; i < 2; i++) {
12097c478bd9Sstevel@tonic-gate 				*m = *m + 1;
12107c478bd9Sstevel@tonic-gate 				oct = p->str[*m];
12117c478bd9Sstevel@tonic-gate 				if ((oct >= '0') && (oct <= '7')) {
12127c478bd9Sstevel@tonic-gate 					value = value * 8 + (oct - '0');
12137c478bd9Sstevel@tonic-gate 				} else {
12147c478bd9Sstevel@tonic-gate 					*m = *m - 1;
12157c478bd9Sstevel@tonic-gate 					break;
12167c478bd9Sstevel@tonic-gate 				}
12177c478bd9Sstevel@tonic-gate 			}
12187c478bd9Sstevel@tonic-gate 			*c = value;
12197c478bd9Sstevel@tonic-gate #ifdef DEBUG
12207c478bd9Sstevel@tonic-gate 			/* (void) fprintf(stderr, "octal=%d\n", value); */
12217c478bd9Sstevel@tonic-gate #endif
12227c478bd9Sstevel@tonic-gate 			break;
12237c478bd9Sstevel@tonic-gate 		case 'x':
12247c478bd9Sstevel@tonic-gate 			value = 0;
12257c478bd9Sstevel@tonic-gate 			/*
12267c478bd9Sstevel@tonic-gate 			 * Remove all heading zeros first and
12277c478bd9Sstevel@tonic-gate 			 * get one or two valuid hexadecimal charaters.
12287c478bd9Sstevel@tonic-gate 			 */
12297c478bd9Sstevel@tonic-gate 			*m = *m + 1;
12307c478bd9Sstevel@tonic-gate 			while (p->str[*m] == '0') {
12317c478bd9Sstevel@tonic-gate 				*m = *m + 1;
12327c478bd9Sstevel@tonic-gate 			}
12337c478bd9Sstevel@tonic-gate 			value = 0;
12347c478bd9Sstevel@tonic-gate 			for (i = 0; i < 2; i++) {
12357c478bd9Sstevel@tonic-gate 				hex = p->str[*m];
12367c478bd9Sstevel@tonic-gate 				*m = *m + 1;
12377c478bd9Sstevel@tonic-gate 				if (isdigit(hex)) {
12387c478bd9Sstevel@tonic-gate 					value = value * 16 + (hex - '0');
12397c478bd9Sstevel@tonic-gate 				} else if (isxdigit(hex)) {
12407c478bd9Sstevel@tonic-gate 					hex = tolower(hex);
12417c478bd9Sstevel@tonic-gate 					value = value * 16 + (hex - 'a' + 10);
12427c478bd9Sstevel@tonic-gate 				} else {
12437c478bd9Sstevel@tonic-gate 					*m = *m - 1;
12447c478bd9Sstevel@tonic-gate 					break;
12457c478bd9Sstevel@tonic-gate 				}
12467c478bd9Sstevel@tonic-gate 			}
12477c478bd9Sstevel@tonic-gate 			*c = value;
12487c478bd9Sstevel@tonic-gate #ifdef DEBUG
12497c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "hex=%d\n", value);
12507c478bd9Sstevel@tonic-gate #endif
12517c478bd9Sstevel@tonic-gate 			*m = *m - 1;
12527c478bd9Sstevel@tonic-gate 			break;
12537c478bd9Sstevel@tonic-gate 		default :
12547c478bd9Sstevel@tonic-gate 			/*
12557c478bd9Sstevel@tonic-gate 			 * Undefined by ANSI.
12567c478bd9Sstevel@tonic-gate 			 * Just ignore "\".
12577c478bd9Sstevel@tonic-gate 			 */
12587c478bd9Sstevel@tonic-gate 			*c = p->str[*m];
12597c478bd9Sstevel@tonic-gate 			break;
12607c478bd9Sstevel@tonic-gate 		}
12617c478bd9Sstevel@tonic-gate 		/*
12627c478bd9Sstevel@tonic-gate 		 * Advance pointer to point the next character to be parsed.
12637c478bd9Sstevel@tonic-gate 		 */
12647c478bd9Sstevel@tonic-gate 		*m = *m + 1;
12657c478bd9Sstevel@tonic-gate 		return (p);
12667c478bd9Sstevel@tonic-gate 	}
12677c478bd9Sstevel@tonic-gate } /* get_next_ch */
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate /*
12707c478bd9Sstevel@tonic-gate  * Compares two msgids.
12717c478bd9Sstevel@tonic-gate  * Comparison is done by values, not by characters represented.
12727c478bd9Sstevel@tonic-gate  * For example, '\t', '\011' and '0x9' are identical values.
12737c478bd9Sstevel@tonic-gate  * Return values are same as in strcmp.
12747c478bd9Sstevel@tonic-gate  *   1   if  msgid1 > msgid2
12757c478bd9Sstevel@tonic-gate  *   0   if  msgid1 = msgid2
12767c478bd9Sstevel@tonic-gate  *  -1   if  msgid1 < msgid2
12777c478bd9Sstevel@tonic-gate  */
12787c478bd9Sstevel@tonic-gate static int
msgidcmp(struct strlist_st * id1,struct strlist_st * id2)12797c478bd9Sstevel@tonic-gate msgidcmp(struct strlist_st *id1, struct strlist_st *id2)
12807c478bd9Sstevel@tonic-gate {
12817c478bd9Sstevel@tonic-gate 	char	c1, c2;
12827c478bd9Sstevel@tonic-gate 	int	m1, m2;
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	m1 = 0;
12857c478bd9Sstevel@tonic-gate 	m2 = 0;
12867c478bd9Sstevel@tonic-gate 
12877c478bd9Sstevel@tonic-gate 	/*CONSTCOND*/
12887c478bd9Sstevel@tonic-gate 	while (1) {
12897c478bd9Sstevel@tonic-gate 		id1 = get_next_ch(id1, &m1, &c1);
12907c478bd9Sstevel@tonic-gate 		id2 = get_next_ch(id2, &m2, &c2);
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 		if ((c1 == 0) && (c2 == 0)) {
12937c478bd9Sstevel@tonic-gate 			return (0);
12947c478bd9Sstevel@tonic-gate 		}
12957c478bd9Sstevel@tonic-gate 
12967c478bd9Sstevel@tonic-gate 		if (c1 > c2) {
12977c478bd9Sstevel@tonic-gate 			return (1);
12987c478bd9Sstevel@tonic-gate 		} else if (c1 < c2) {
12997c478bd9Sstevel@tonic-gate 			return (-1);
13007c478bd9Sstevel@tonic-gate 		}
13017c478bd9Sstevel@tonic-gate 	}
13027c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
13037c478bd9Sstevel@tonic-gate } /* msgidcmp */
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate /*
13067c478bd9Sstevel@tonic-gate  * Check if a ANSI string (which is a linked list itself) is a duplicate
13077c478bd9Sstevel@tonic-gate  * of any string in the list of ANSI string.
13087c478bd9Sstevel@tonic-gate  */
13097c478bd9Sstevel@tonic-gate static int
isduplicate(struct element_st * list,struct strlist_st * str)13107c478bd9Sstevel@tonic-gate isduplicate(struct element_st *list, struct strlist_st *str)
13117c478bd9Sstevel@tonic-gate {
13127c478bd9Sstevel@tonic-gate 	struct element_st	*p;
13137c478bd9Sstevel@tonic-gate 
13147c478bd9Sstevel@tonic-gate 	if (list == NULL) {
13157c478bd9Sstevel@tonic-gate 		return (FALSE);
13167c478bd9Sstevel@tonic-gate 	}
13177c478bd9Sstevel@tonic-gate 
13187c478bd9Sstevel@tonic-gate 	p = list;
13197c478bd9Sstevel@tonic-gate 	while (p != NULL) {
13207c478bd9Sstevel@tonic-gate 		if (p->msgid != NULL) {
13217c478bd9Sstevel@tonic-gate 			if (msgidcmp(p->msgid, str) == 0) {
13227c478bd9Sstevel@tonic-gate 				return (TRUE);
13237c478bd9Sstevel@tonic-gate 			}
13247c478bd9Sstevel@tonic-gate 		}
13257c478bd9Sstevel@tonic-gate 		p = p->next;
13267c478bd9Sstevel@tonic-gate 	}
13277c478bd9Sstevel@tonic-gate 
13287c478bd9Sstevel@tonic-gate 	return (FALSE);
13297c478bd9Sstevel@tonic-gate } /* isduplicate */
13307c478bd9Sstevel@tonic-gate 
13317c478bd9Sstevel@tonic-gate /*
13327c478bd9Sstevel@tonic-gate  * Extract a comment line and add to the linked list containing
13337c478bd9Sstevel@tonic-gate  * comment block.
13347c478bd9Sstevel@tonic-gate  * Each comment line is stored in the node.
13357c478bd9Sstevel@tonic-gate  */
13367c478bd9Sstevel@tonic-gate static void
add_line_to_comment(void)13377c478bd9Sstevel@tonic-gate add_line_to_comment(void)
13387c478bd9Sstevel@tonic-gate {
13397c478bd9Sstevel@tonic-gate 	struct strlist_st	*tmp_str;
13407c478bd9Sstevel@tonic-gate 
13417c478bd9Sstevel@tonic-gate 	tmp_str = new_strlist();
13427c478bd9Sstevel@tonic-gate 	tmp_str->str = strdup(curr_line);
13437c478bd9Sstevel@tonic-gate 	tmp_str->next = NULL;
13447c478bd9Sstevel@tonic-gate 
13457c478bd9Sstevel@tonic-gate 	if (commhead == NULL) {
13467c478bd9Sstevel@tonic-gate 		/* Empty comment list */
13477c478bd9Sstevel@tonic-gate 		commhead = tmp_str;
13487c478bd9Sstevel@tonic-gate 		commtail = tmp_str;
13497c478bd9Sstevel@tonic-gate 	} else {
13507c478bd9Sstevel@tonic-gate 		/* append it to the list */
13517c478bd9Sstevel@tonic-gate 		commtail->next = tmp_str;
13527c478bd9Sstevel@tonic-gate 		commtail = commtail->next;
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	is_last_comment_line = FALSE;
13567c478bd9Sstevel@tonic-gate } /* add_line_to_comment */
13577c478bd9Sstevel@tonic-gate 
13587c478bd9Sstevel@tonic-gate /*
13597c478bd9Sstevel@tonic-gate  * Add a double quoted string to the linked list containing ANSI string.
13607c478bd9Sstevel@tonic-gate  */
13617c478bd9Sstevel@tonic-gate static void
add_qstring_to_str(void)13627c478bd9Sstevel@tonic-gate add_qstring_to_str(void)
13637c478bd9Sstevel@tonic-gate {
13647c478bd9Sstevel@tonic-gate 	struct strlist_st	*tmp_str;
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	tmp_str = new_strlist();
13677c478bd9Sstevel@tonic-gate 	tmp_str->str = strdup(qstring_buf);
13687c478bd9Sstevel@tonic-gate 	tmp_str->next = NULL;
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	if (strhead == NULL) {
13717c478bd9Sstevel@tonic-gate 		/* Null ANSI string */
13727c478bd9Sstevel@tonic-gate 		strhead = tmp_str;
13737c478bd9Sstevel@tonic-gate 		strtail = tmp_str;
13747c478bd9Sstevel@tonic-gate 	} else {
13757c478bd9Sstevel@tonic-gate 		/* Append it to the ANSI string linked list */
13767c478bd9Sstevel@tonic-gate 		strtail->next = tmp_str;
13777c478bd9Sstevel@tonic-gate 		strtail = strtail->next;
13787c478bd9Sstevel@tonic-gate 	}
13797c478bd9Sstevel@tonic-gate 
1380*df69b316SToomas Soome 	qstring_buf[0] = '\0';
13817c478bd9Sstevel@tonic-gate } /* add_qstring_to_str */
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate /*
13847c478bd9Sstevel@tonic-gate  * Finds the head of domain nodes given domain name.
13857c478bd9Sstevel@tonic-gate  */
13867c478bd9Sstevel@tonic-gate static struct domain_st *
find_domain_node(char * dname)13877c478bd9Sstevel@tonic-gate find_domain_node(char *dname)
13887c478bd9Sstevel@tonic-gate {
13897c478bd9Sstevel@tonic-gate 	struct domain_st	*tmp_dom, *p;
13907c478bd9Sstevel@tonic-gate 
13917c478bd9Sstevel@tonic-gate 	/*
13927c478bd9Sstevel@tonic-gate 	 * If -a option is specified everything will be written to the
13937c478bd9Sstevel@tonic-gate 	 * default domain file.
13947c478bd9Sstevel@tonic-gate 	 */
13957c478bd9Sstevel@tonic-gate 	if (aflg == TRUE) {
13967c478bd9Sstevel@tonic-gate 		if (def_dom == NULL) {
13977c478bd9Sstevel@tonic-gate 			def_dom = new_domain();
13987c478bd9Sstevel@tonic-gate 		}
13997c478bd9Sstevel@tonic-gate 		return (def_dom);
14007c478bd9Sstevel@tonic-gate 	}
14017c478bd9Sstevel@tonic-gate 
14027c478bd9Sstevel@tonic-gate 	if ((dname == NULL) ||
1403*df69b316SToomas Soome 	    (dname[0] == '\0') ||
14047c478bd9Sstevel@tonic-gate 	    (strcmp(dname, default_domain) == 0)) {
14057c478bd9Sstevel@tonic-gate 		if (def_dom == NULL) {
14067c478bd9Sstevel@tonic-gate 			def_dom = new_domain();
14077c478bd9Sstevel@tonic-gate 		}
14087c478bd9Sstevel@tonic-gate 		if (strcmp(dname, default_domain) == 0) {
1409*df69b316SToomas Soome 			(void) fprintf(stderr, "%s \"%s\" is used in dgettext "
1410*df69b316SToomas Soome 			    "of file:%s line:%d.\n",
1411*df69b316SToomas Soome 			    "Warning: default domain name",
1412*df69b316SToomas Soome 			    default_domain, curr_file, curr_linenum);
14137c478bd9Sstevel@tonic-gate 		}
14147c478bd9Sstevel@tonic-gate 		return (def_dom);
14157c478bd9Sstevel@tonic-gate 	} else {
14167c478bd9Sstevel@tonic-gate 		p = dom_head;
14177c478bd9Sstevel@tonic-gate 		while (p != NULL) {
14187c478bd9Sstevel@tonic-gate 			if (strcmp(p->dname, dname) == 0) {
14197c478bd9Sstevel@tonic-gate 				return (p);
14207c478bd9Sstevel@tonic-gate 			}
14217c478bd9Sstevel@tonic-gate 			p = p->next;
14227c478bd9Sstevel@tonic-gate 		}
14237c478bd9Sstevel@tonic-gate 
14247c478bd9Sstevel@tonic-gate 		tmp_dom = new_domain();
14257c478bd9Sstevel@tonic-gate 		tmp_dom->dname = strdup(dname);
14267c478bd9Sstevel@tonic-gate 
14277c478bd9Sstevel@tonic-gate 		if (dom_head == NULL) {
14287c478bd9Sstevel@tonic-gate 			dom_head = tmp_dom;
14297c478bd9Sstevel@tonic-gate 			dom_tail = tmp_dom;
14307c478bd9Sstevel@tonic-gate 		} else {
14317c478bd9Sstevel@tonic-gate 			dom_tail->next = tmp_dom;
14327c478bd9Sstevel@tonic-gate 			dom_tail = dom_tail->next;
14337c478bd9Sstevel@tonic-gate 		}
14347c478bd9Sstevel@tonic-gate 		return (tmp_dom);
14357c478bd9Sstevel@tonic-gate 	}
14367c478bd9Sstevel@tonic-gate } /* find_domain_node */
14377c478bd9Sstevel@tonic-gate 
14387c478bd9Sstevel@tonic-gate /*
14397c478bd9Sstevel@tonic-gate  * Frees the ANSI string linked list.
14407c478bd9Sstevel@tonic-gate  */
14417c478bd9Sstevel@tonic-gate static void
free_strlist(struct strlist_st * ptr)14427c478bd9Sstevel@tonic-gate free_strlist(struct strlist_st *ptr)
14437c478bd9Sstevel@tonic-gate {
14447c478bd9Sstevel@tonic-gate 	struct strlist_st	*p;
14457c478bd9Sstevel@tonic-gate 
14467c478bd9Sstevel@tonic-gate 	p = ptr;
14477c478bd9Sstevel@tonic-gate 	ptr = NULL;
14487c478bd9Sstevel@tonic-gate 	while (p != NULL) {
14497c478bd9Sstevel@tonic-gate 		ptr = p->next;
14507c478bd9Sstevel@tonic-gate 		free(p->str);
14517c478bd9Sstevel@tonic-gate 		free(p);
14527c478bd9Sstevel@tonic-gate 		p = ptr;
14537c478bd9Sstevel@tonic-gate 	}
14547c478bd9Sstevel@tonic-gate } /* free_strlist */
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate /*
14577c478bd9Sstevel@tonic-gate  * Finds if a ANSI string is contained in the exclude file.
14587c478bd9Sstevel@tonic-gate  */
14597c478bd9Sstevel@tonic-gate static int
isexcluded(struct strlist_st * strlist)14607c478bd9Sstevel@tonic-gate isexcluded(struct strlist_st *strlist)
14617c478bd9Sstevel@tonic-gate {
14627c478bd9Sstevel@tonic-gate 	struct exclude_st	*p;
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 	p = excl_head;
14657c478bd9Sstevel@tonic-gate 	while (p != NULL) {
14667c478bd9Sstevel@tonic-gate 		if (msgidcmp(p->exstr, strlist) == 0) {
14677c478bd9Sstevel@tonic-gate 			return (TRUE);
14687c478bd9Sstevel@tonic-gate 		}
14697c478bd9Sstevel@tonic-gate 		p = p->next;
14707c478bd9Sstevel@tonic-gate 	}
14717c478bd9Sstevel@tonic-gate 	return (FALSE);
14727c478bd9Sstevel@tonic-gate } /* isexcluded */
14737c478bd9Sstevel@tonic-gate 
14747c478bd9Sstevel@tonic-gate /*
14757c478bd9Sstevel@tonic-gate  * Finds if a comment block is to be extracted.
14767c478bd9Sstevel@tonic-gate  *
14777c478bd9Sstevel@tonic-gate  * When -c option is specified, find out if comment block contains
14787c478bd9Sstevel@tonic-gate  * comment-tag as a token separated by blanks. If it does, this
14797c478bd9Sstevel@tonic-gate  * comment block is associated with the next msgid encountered.
14807c478bd9Sstevel@tonic-gate  * Comment block is a linked list where each node contains one line
14817c478bd9Sstevel@tonic-gate  * of comments.
14827c478bd9Sstevel@tonic-gate  */
14837c478bd9Sstevel@tonic-gate static int
isextracted(struct strlist_st * strlist)14847c478bd9Sstevel@tonic-gate isextracted(struct strlist_st *strlist)
14857c478bd9Sstevel@tonic-gate {
14867c478bd9Sstevel@tonic-gate 	struct strlist_st	*p;
14877c478bd9Sstevel@tonic-gate 	char			*first, *pc;
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 
14907c478bd9Sstevel@tonic-gate 	p = strlist;
14917c478bd9Sstevel@tonic-gate 	while (p != NULL) {
14927c478bd9Sstevel@tonic-gate 		first = strdup(p->str);
1493*df69b316SToomas Soome 		while ((first != NULL) && (first[0] != '\0')) {
14947c478bd9Sstevel@tonic-gate 			pc = first;
14957c478bd9Sstevel@tonic-gate 
14967c478bd9Sstevel@tonic-gate 			/*CONSTCOND*/
14977c478bd9Sstevel@tonic-gate 			while (1) {
1498*df69b316SToomas Soome 				if (*pc == '\0') {
14997c478bd9Sstevel@tonic-gate 					break;
15007c478bd9Sstevel@tonic-gate 				} else if ((*pc == ' ') || (*pc == '\t')) {
1501*df69b316SToomas Soome 					*pc++ = '\0';
15027c478bd9Sstevel@tonic-gate 					break;
15037c478bd9Sstevel@tonic-gate 				}
15047c478bd9Sstevel@tonic-gate 				pc++;
15057c478bd9Sstevel@tonic-gate 			}
15067c478bd9Sstevel@tonic-gate 			if (strcmp(first, comment_tag) == 0) {
15077c478bd9Sstevel@tonic-gate 				return (TRUE);
15087c478bd9Sstevel@tonic-gate 			}
15097c478bd9Sstevel@tonic-gate 			first = pc;
15107c478bd9Sstevel@tonic-gate 		}
15117c478bd9Sstevel@tonic-gate 		p = p->next;
15127c478bd9Sstevel@tonic-gate 	} /* while */
15137c478bd9Sstevel@tonic-gate 
15147c478bd9Sstevel@tonic-gate 	/*
15157c478bd9Sstevel@tonic-gate 	 * Not found.
15167c478bd9Sstevel@tonic-gate 	 */
15177c478bd9Sstevel@tonic-gate 	return (FALSE);
15187c478bd9Sstevel@tonic-gate } /* isextracted */
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate /*
15217c478bd9Sstevel@tonic-gate  * Adds ANSI string to the domain element list.
15227c478bd9Sstevel@tonic-gate  */
15237c478bd9Sstevel@tonic-gate static void
add_str_to_element_list(int istextdomain,char * domain_list)15247c478bd9Sstevel@tonic-gate add_str_to_element_list(int istextdomain, char *domain_list)
15257c478bd9Sstevel@tonic-gate {
15267c478bd9Sstevel@tonic-gate 	struct element_st	*tmp_elem;
15277c478bd9Sstevel@tonic-gate 	struct element_st	*p, *q;
15287c478bd9Sstevel@tonic-gate 	struct domain_st	*tmp_dom;
15297c478bd9Sstevel@tonic-gate 	int			result;
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate 	/*
15327c478bd9Sstevel@tonic-gate 	 * This can happen if something like gettext(USAGE) is used
15337c478bd9Sstevel@tonic-gate 	 * and it is impossible to get msgid for this gettext.
15347c478bd9Sstevel@tonic-gate 	 * Since -x option should be used in this kind of cases,
15357c478bd9Sstevel@tonic-gate 	 * it is OK not to catch msgid.
15367c478bd9Sstevel@tonic-gate 	 */
15377c478bd9Sstevel@tonic-gate 	if (strhead == NULL) {
15387c478bd9Sstevel@tonic-gate 		return;
15397c478bd9Sstevel@tonic-gate 	}
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 	/*
15427c478bd9Sstevel@tonic-gate 	 * The global variable curr_domain contains either NULL
15437c478bd9Sstevel@tonic-gate 	 * for default_domain or domain name for dgettext().
15447c478bd9Sstevel@tonic-gate 	 */
15457c478bd9Sstevel@tonic-gate 	tmp_dom = find_domain_node(domain_list);
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 	/*
15487c478bd9Sstevel@tonic-gate 	 * If this msgid is in the exclude file,
15497c478bd9Sstevel@tonic-gate 	 * then free the linked list and return.
15507c478bd9Sstevel@tonic-gate 	 */
15517c478bd9Sstevel@tonic-gate 	if ((istextdomain == FALSE) &&
15527c478bd9Sstevel@tonic-gate 	    (isexcluded(strhead) == TRUE)) {
15537c478bd9Sstevel@tonic-gate 		free_strlist(strhead);
15547c478bd9Sstevel@tonic-gate 		strhead = strtail = NULL;
15557c478bd9Sstevel@tonic-gate 		return;
15567c478bd9Sstevel@tonic-gate 	}
15577c478bd9Sstevel@tonic-gate 
15587c478bd9Sstevel@tonic-gate 	tmp_elem = new_element();
15597c478bd9Sstevel@tonic-gate 	tmp_elem->msgid = strhead;
15607c478bd9Sstevel@tonic-gate 	tmp_elem->istextdomain = istextdomain;
15617c478bd9Sstevel@tonic-gate 	/*
15627c478bd9Sstevel@tonic-gate 	 * If -c option is specified and TAG matches,
15637c478bd9Sstevel@tonic-gate 	 * then associate the comment to the next [d]gettext() calls
15647c478bd9Sstevel@tonic-gate 	 * encountered in the source code.
15657c478bd9Sstevel@tonic-gate 	 * textdomain() calls will not have any effect.
15667c478bd9Sstevel@tonic-gate 	 */
15677c478bd9Sstevel@tonic-gate 	if (istextdomain == FALSE) {
15687c478bd9Sstevel@tonic-gate 		if ((cflg == TRUE) && (commhead != NULL)) {
15697c478bd9Sstevel@tonic-gate 			if (isextracted(commhead) == TRUE) {
15707c478bd9Sstevel@tonic-gate 				tmp_elem->comment = commhead;
15717c478bd9Sstevel@tonic-gate 			} else {
15727c478bd9Sstevel@tonic-gate 				free_strlist(commhead);
15737c478bd9Sstevel@tonic-gate 			}
15747c478bd9Sstevel@tonic-gate 			commhead = commtail = NULL;
15757c478bd9Sstevel@tonic-gate 		}
15767c478bd9Sstevel@tonic-gate 	}
15777c478bd9Sstevel@tonic-gate 
15787c478bd9Sstevel@tonic-gate 	tmp_elem->linenum = linenum_saved;
15797c478bd9Sstevel@tonic-gate 	tmp_elem->fname = strdup(curr_file);
15807c478bd9Sstevel@tonic-gate 
15817c478bd9Sstevel@tonic-gate 
15827c478bd9Sstevel@tonic-gate 	if (sflg == TRUE) {
15837c478bd9Sstevel@tonic-gate 		/*
15847c478bd9Sstevel@tonic-gate 		 * If this is textdomain() call and -s option is specified,
15857c478bd9Sstevel@tonic-gate 		 * append this node to the textdomain linked list.
15867c478bd9Sstevel@tonic-gate 		 */
15877c478bd9Sstevel@tonic-gate 		if (istextdomain == TRUE) {
15887c478bd9Sstevel@tonic-gate 			if (tmp_dom->textdomain_head == NULL) {
15897c478bd9Sstevel@tonic-gate 				tmp_dom->textdomain_head = tmp_elem;
15907c478bd9Sstevel@tonic-gate 				tmp_dom->textdomain_tail = tmp_elem;
15917c478bd9Sstevel@tonic-gate 			} else {
15927c478bd9Sstevel@tonic-gate 				tmp_dom->textdomain_tail->next = tmp_elem;
15937c478bd9Sstevel@tonic-gate 				tmp_dom->textdomain_tail = tmp_elem;
15947c478bd9Sstevel@tonic-gate 			}
15957c478bd9Sstevel@tonic-gate 			strhead = strtail = NULL;
15967c478bd9Sstevel@tonic-gate 			return;
15977c478bd9Sstevel@tonic-gate 		}
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate 		/*
16007c478bd9Sstevel@tonic-gate 		 * Insert the node to the properly sorted position.
16017c478bd9Sstevel@tonic-gate 		 */
16027c478bd9Sstevel@tonic-gate 		q = NULL;
16037c478bd9Sstevel@tonic-gate 		p = tmp_dom->gettext_head;
16047c478bd9Sstevel@tonic-gate 		while (p != NULL) {
16057c478bd9Sstevel@tonic-gate 			result = msgidcmp(strhead, p->msgid);
16067c478bd9Sstevel@tonic-gate 			if (result == 0) {
16077c478bd9Sstevel@tonic-gate 				/*
16087c478bd9Sstevel@tonic-gate 				 * Duplicate id. Do not store.
16097c478bd9Sstevel@tonic-gate 				 */
16107c478bd9Sstevel@tonic-gate 				free_strlist(strhead);
16117c478bd9Sstevel@tonic-gate 				strhead = strtail = NULL;
16127c478bd9Sstevel@tonic-gate 				return;
16137c478bd9Sstevel@tonic-gate 			} else if (result > 0) {
16147c478bd9Sstevel@tonic-gate 				/* move to the next node */
16157c478bd9Sstevel@tonic-gate 				q = p;
16167c478bd9Sstevel@tonic-gate 				p = p->next;
16177c478bd9Sstevel@tonic-gate 			} else {
16187c478bd9Sstevel@tonic-gate 				tmp_elem->next = p;
16197c478bd9Sstevel@tonic-gate 				if (q != NULL) {
16207c478bd9Sstevel@tonic-gate 					q->next = tmp_elem;
16217c478bd9Sstevel@tonic-gate 				} else {
16227c478bd9Sstevel@tonic-gate 					tmp_dom->gettext_head = tmp_elem;
16237c478bd9Sstevel@tonic-gate 				}
16247c478bd9Sstevel@tonic-gate 				strhead = strtail = NULL;
16257c478bd9Sstevel@tonic-gate 				return;
16267c478bd9Sstevel@tonic-gate 			}
16277c478bd9Sstevel@tonic-gate 		} /* while */
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 		/*
16307c478bd9Sstevel@tonic-gate 		 * New msgid is the largest or empty list.
16317c478bd9Sstevel@tonic-gate 		 */
16327c478bd9Sstevel@tonic-gate 		if (q != NULL) {
16337c478bd9Sstevel@tonic-gate 			/* largest case */
16347c478bd9Sstevel@tonic-gate 			q->next = tmp_elem;
16357c478bd9Sstevel@tonic-gate 		} else {
16367c478bd9Sstevel@tonic-gate 			/* empty list */
16377c478bd9Sstevel@tonic-gate 			tmp_dom->gettext_head = tmp_elem;
16387c478bd9Sstevel@tonic-gate 		}
16397c478bd9Sstevel@tonic-gate 	} else {
16407c478bd9Sstevel@tonic-gate 		/*
16417c478bd9Sstevel@tonic-gate 		 * Check if this msgid is already in the same domain.
16427c478bd9Sstevel@tonic-gate 		 */
16437c478bd9Sstevel@tonic-gate 		if (tmp_dom != NULL) {
16447c478bd9Sstevel@tonic-gate 			if (isduplicate(tmp_dom->gettext_head,
1645*df69b316SToomas Soome 			    tmp_elem->msgid) == TRUE) {
16467c478bd9Sstevel@tonic-gate 				tmp_elem->isduplicate = TRUE;
16477c478bd9Sstevel@tonic-gate 			}
16487c478bd9Sstevel@tonic-gate 		}
16497c478bd9Sstevel@tonic-gate 		/*
16507c478bd9Sstevel@tonic-gate 		 * If -s option is not specified, then everything
16517c478bd9Sstevel@tonic-gate 		 * is stored in gettext linked list.
16527c478bd9Sstevel@tonic-gate 		 */
16537c478bd9Sstevel@tonic-gate 		if (tmp_dom->gettext_head == NULL) {
16547c478bd9Sstevel@tonic-gate 			tmp_dom->gettext_head = tmp_elem;
16557c478bd9Sstevel@tonic-gate 			tmp_dom->gettext_tail = tmp_elem;
16567c478bd9Sstevel@tonic-gate 		} else {
16577c478bd9Sstevel@tonic-gate 			tmp_dom->gettext_tail->next = tmp_elem;
16587c478bd9Sstevel@tonic-gate 			tmp_dom->gettext_tail = tmp_elem;
16597c478bd9Sstevel@tonic-gate 		}
16607c478bd9Sstevel@tonic-gate 	}
16617c478bd9Sstevel@tonic-gate 
16627c478bd9Sstevel@tonic-gate 	strhead = strtail = NULL;
16637c478bd9Sstevel@tonic-gate } /* add_str_to_element_list */
16647c478bd9Sstevel@tonic-gate 
16657c478bd9Sstevel@tonic-gate /*
16667c478bd9Sstevel@tonic-gate  * Write all domain linked list to the files.
16677c478bd9Sstevel@tonic-gate  */
16687c478bd9Sstevel@tonic-gate static void
write_all_files(void)16697c478bd9Sstevel@tonic-gate write_all_files(void)
16707c478bd9Sstevel@tonic-gate {
16717c478bd9Sstevel@tonic-gate 	struct domain_st	*tmp;
16727c478bd9Sstevel@tonic-gate 
16737c478bd9Sstevel@tonic-gate 	/*
16747c478bd9Sstevel@tonic-gate 	 * Write out default domain file.
16757c478bd9Sstevel@tonic-gate 	 */
16767c478bd9Sstevel@tonic-gate 	write_one_file(def_dom);
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate 	/*
16797c478bd9Sstevel@tonic-gate 	 * If dgettext() exists and -a option is not used,
16807c478bd9Sstevel@tonic-gate 	 * then there are non-empty linked list.
16817c478bd9Sstevel@tonic-gate 	 */
16827c478bd9Sstevel@tonic-gate 	tmp = dom_head;
16837c478bd9Sstevel@tonic-gate 	while (tmp != NULL) {
16847c478bd9Sstevel@tonic-gate 		write_one_file(tmp);
16857c478bd9Sstevel@tonic-gate 		tmp = tmp->next;
16867c478bd9Sstevel@tonic-gate 	}
16877c478bd9Sstevel@tonic-gate } /* write_all_files */
16887c478bd9Sstevel@tonic-gate 
16897c478bd9Sstevel@tonic-gate /*
16907c478bd9Sstevel@tonic-gate  * add an element_st list to the linked list.
16917c478bd9Sstevel@tonic-gate  */
16927c478bd9Sstevel@tonic-gate static void
add_node_to_polist(struct element_st ** pohead,struct element_st ** potail,struct element_st * elem)16937c478bd9Sstevel@tonic-gate add_node_to_polist(struct element_st **pohead,
1694*df69b316SToomas Soome     struct element_st **potail, struct element_st *elem)
16957c478bd9Sstevel@tonic-gate {
16967c478bd9Sstevel@tonic-gate 	if (elem == NULL) {
16977c478bd9Sstevel@tonic-gate 		return;
16987c478bd9Sstevel@tonic-gate 	}
16997c478bd9Sstevel@tonic-gate 
17007c478bd9Sstevel@tonic-gate 	if (*pohead == NULL) {
17017c478bd9Sstevel@tonic-gate 		*pohead = *potail = elem;
17027c478bd9Sstevel@tonic-gate 	} else {
17037c478bd9Sstevel@tonic-gate 		(*potail)->next = elem;
17047c478bd9Sstevel@tonic-gate 		*potail = (*potail)->next;
17057c478bd9Sstevel@tonic-gate 	}
17067c478bd9Sstevel@tonic-gate } /* add_node_to_polist */
17077c478bd9Sstevel@tonic-gate 
17087c478bd9Sstevel@tonic-gate #define	INIT_STATE	0
17097c478bd9Sstevel@tonic-gate #define	IN_MSGID	1
17107c478bd9Sstevel@tonic-gate #define	IN_MSGSTR	2
17117c478bd9Sstevel@tonic-gate #define	IN_COMMENT	3
17127c478bd9Sstevel@tonic-gate /*
17137c478bd9Sstevel@tonic-gate  * Reads existing po file into the linked list and returns the head
17147c478bd9Sstevel@tonic-gate  * of the linked list.
17157c478bd9Sstevel@tonic-gate  */
17167c478bd9Sstevel@tonic-gate static struct element_st *
read_po(char * fname)17177c478bd9Sstevel@tonic-gate read_po(char *fname)
17187c478bd9Sstevel@tonic-gate {
17197c478bd9Sstevel@tonic-gate 	struct element_st	*tmp_elem = NULL;
17207c478bd9Sstevel@tonic-gate 	struct element_st	*ehead = NULL, *etail = NULL;
17217c478bd9Sstevel@tonic-gate 	struct strlist_st	*comment_tail = NULL;
17227c478bd9Sstevel@tonic-gate 	struct strlist_st	*msgid_tail = NULL;
17237c478bd9Sstevel@tonic-gate 	struct strlist_st	*msgstr_tail = NULL;
17247c478bd9Sstevel@tonic-gate 	int			state = INIT_STATE;
17257c478bd9Sstevel@tonic-gate 	char			line [MAX_STRING_LEN];
17267c478bd9Sstevel@tonic-gate 	FILE			*fp;
17277c478bd9Sstevel@tonic-gate 
17287c478bd9Sstevel@tonic-gate 	if ((fp = fopen(fname, "r")) == NULL) {
17297c478bd9Sstevel@tonic-gate 		return (NULL);
17307c478bd9Sstevel@tonic-gate 	}
17317c478bd9Sstevel@tonic-gate 
17327c478bd9Sstevel@tonic-gate 	while (fgets(line, MAX_STRING_LEN, fp) != NULL) {
17337c478bd9Sstevel@tonic-gate 		/*
17347c478bd9Sstevel@tonic-gate 		 * Line starting with # is a comment line and ignored.
17357c478bd9Sstevel@tonic-gate 		 * Blank line is ignored, too.
17367c478bd9Sstevel@tonic-gate 		 */
17377c478bd9Sstevel@tonic-gate 		if (line[0] == '\n') {
17387c478bd9Sstevel@tonic-gate 			continue;
17397c478bd9Sstevel@tonic-gate 		} else if (line[0] == '#') {
17407c478bd9Sstevel@tonic-gate 			/*
17417c478bd9Sstevel@tonic-gate 			 * If tmp_elem is not NULL, there is msgid pair
17427c478bd9Sstevel@tonic-gate 			 * stored. Therefore, add it.
17437c478bd9Sstevel@tonic-gate 			 */
17447c478bd9Sstevel@tonic-gate 			if ((tmp_elem != NULL) && (state == IN_MSGSTR)) {
17457c478bd9Sstevel@tonic-gate 				add_node_to_polist(&ehead, &etail, tmp_elem);
17467c478bd9Sstevel@tonic-gate 			}
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 			if ((state == INIT_STATE) || (state == IN_MSGSTR)) {
17497c478bd9Sstevel@tonic-gate 				state = IN_COMMENT;
17507c478bd9Sstevel@tonic-gate 				tmp_elem = new_element();
17517c478bd9Sstevel@tonic-gate 				tmp_elem->comment = comment_tail =
1752*df69b316SToomas Soome 				    new_strlist();
17537c478bd9Sstevel@tonic-gate 				/*
17547c478bd9Sstevel@tonic-gate 				 * remove new line and skip "# "
17557c478bd9Sstevel@tonic-gate 				 * in the beginning of the existing
17567c478bd9Sstevel@tonic-gate 				 * comment line.
17577c478bd9Sstevel@tonic-gate 				 */
17587c478bd9Sstevel@tonic-gate 				line[strlen(line)-1] = 0;
17597c478bd9Sstevel@tonic-gate 				comment_tail->str = strdup(line+2);
17607c478bd9Sstevel@tonic-gate 			} else if (state == IN_COMMENT) {
17617c478bd9Sstevel@tonic-gate 				comment_tail->next = new_strlist();
17627c478bd9Sstevel@tonic-gate 				comment_tail = comment_tail->next;
17637c478bd9Sstevel@tonic-gate 				/*
17647c478bd9Sstevel@tonic-gate 				 * remove new line and skip "# "
17657c478bd9Sstevel@tonic-gate 				 * in the beginning of the existing
17667c478bd9Sstevel@tonic-gate 				 * comment line.
17677c478bd9Sstevel@tonic-gate 				 */
17687c478bd9Sstevel@tonic-gate 				line[strlen(line)-1] = 0;
17697c478bd9Sstevel@tonic-gate 				comment_tail->str = strdup(line+2);
17707c478bd9Sstevel@tonic-gate 			}
17717c478bd9Sstevel@tonic-gate 
17727c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "domain", 6) == 0) {
17737c478bd9Sstevel@tonic-gate 			/* ignore domain line */
17747c478bd9Sstevel@tonic-gate 			continue;
17757c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "msgid", 5) == 0) {
17767c478bd9Sstevel@tonic-gate 			if (state == IN_MSGSTR) {
17777c478bd9Sstevel@tonic-gate 				add_node_to_polist(&ehead, &etail, tmp_elem);
17787c478bd9Sstevel@tonic-gate 				tmp_elem = new_element();
17797c478bd9Sstevel@tonic-gate 			} else if (state == INIT_STATE) {
17807c478bd9Sstevel@tonic-gate 				tmp_elem = new_element();
17817c478bd9Sstevel@tonic-gate 			}
17827c478bd9Sstevel@tonic-gate 
17837c478bd9Sstevel@tonic-gate 			state = IN_MSGID;
17847c478bd9Sstevel@tonic-gate 			trim_line(line);
17857c478bd9Sstevel@tonic-gate 			tmp_elem->msgid = msgid_tail = new_strlist();
17867c478bd9Sstevel@tonic-gate 			msgid_tail->str = strdup(line);
17877c478bd9Sstevel@tonic-gate 
17887c478bd9Sstevel@tonic-gate 		} else if (strncmp(line, "msgstr", 6) == 0) {
17897c478bd9Sstevel@tonic-gate 			state = IN_MSGSTR;
17907c478bd9Sstevel@tonic-gate 			trim_line(line);
17917c478bd9Sstevel@tonic-gate 			tmp_elem->msgstr = msgstr_tail = new_strlist();
17927c478bd9Sstevel@tonic-gate 			msgstr_tail->str = strdup(line);
17937c478bd9Sstevel@tonic-gate 		} else {
17947c478bd9Sstevel@tonic-gate 			/*
17957c478bd9Sstevel@tonic-gate 			 * If more than one line of string forms msgid,
17967c478bd9Sstevel@tonic-gate 			 * append it to the string linked list.
17977c478bd9Sstevel@tonic-gate 			 */
17987c478bd9Sstevel@tonic-gate 			if (state == IN_MSGID) {
17997c478bd9Sstevel@tonic-gate 				trim_line(line);
18007c478bd9Sstevel@tonic-gate 				msgid_tail->next = new_strlist();
18017c478bd9Sstevel@tonic-gate 				msgid_tail = msgid_tail->next;
18027c478bd9Sstevel@tonic-gate 				msgid_tail->str = strdup(line);
18037c478bd9Sstevel@tonic-gate 			} else if (state == IN_MSGSTR) {
18047c478bd9Sstevel@tonic-gate 				trim_line(line);
18057c478bd9Sstevel@tonic-gate 				msgstr_tail->next = new_strlist();
18067c478bd9Sstevel@tonic-gate 				msgstr_tail = msgstr_tail->next;
18077c478bd9Sstevel@tonic-gate 				msgstr_tail->str = strdup(line);
18087c478bd9Sstevel@tonic-gate 			}
18097c478bd9Sstevel@tonic-gate 		}
18107c478bd9Sstevel@tonic-gate 	} /* while */
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	/*
18137c478bd9Sstevel@tonic-gate 	 * To insert the last msgid pair.
18147c478bd9Sstevel@tonic-gate 	 */
18157c478bd9Sstevel@tonic-gate 	if (tmp_elem != NULL) {
18167c478bd9Sstevel@tonic-gate 		add_node_to_polist(&ehead, &etail, tmp_elem);
18177c478bd9Sstevel@tonic-gate 	}
18187c478bd9Sstevel@tonic-gate 
18197c478bd9Sstevel@tonic-gate #ifdef DEBUG
18207c478bd9Sstevel@tonic-gate 	{
18217c478bd9Sstevel@tonic-gate 		struct domain_st *tmp_domain = new_domain();
18227c478bd9Sstevel@tonic-gate 		char	tmpstr[256];
18237c478bd9Sstevel@tonic-gate 
18247c478bd9Sstevel@tonic-gate 		sprintf(tmpstr, "existing_po file : <%s>", fname);
18257c478bd9Sstevel@tonic-gate 		tmp_domain->dname = strdup(tmpstr);
18267c478bd9Sstevel@tonic-gate 		tmp_domain->gettext_head = ehead;
18277c478bd9Sstevel@tonic-gate 		printf("======= existing po file <%s>  ========\n", fname);
18287c478bd9Sstevel@tonic-gate 		print_one_domain(tmp_domain);
18297c478bd9Sstevel@tonic-gate 	}
18307c478bd9Sstevel@tonic-gate #endif /* DEBUG */
18317c478bd9Sstevel@tonic-gate 
18327c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
18337c478bd9Sstevel@tonic-gate 	return (ehead);
18347c478bd9Sstevel@tonic-gate } /* read_po */
18357c478bd9Sstevel@tonic-gate 
18367c478bd9Sstevel@tonic-gate /*
18377c478bd9Sstevel@tonic-gate  * This function will append the second list to the first list.
18387c478bd9Sstevel@tonic-gate  * If the msgid in the second list contains msgid in the first list,
18397c478bd9Sstevel@tonic-gate  * it will be marked as duplicate.
18407c478bd9Sstevel@tonic-gate  */
18417c478bd9Sstevel@tonic-gate static struct element_st *
append_list(struct element_st * l1,struct element_st * l2)18427c478bd9Sstevel@tonic-gate append_list(struct element_st *l1, struct element_st *l2)
18437c478bd9Sstevel@tonic-gate {
18447c478bd9Sstevel@tonic-gate 	struct element_st	*p = NULL, *q = NULL, *l1_tail = NULL;
18457c478bd9Sstevel@tonic-gate 
18467c478bd9Sstevel@tonic-gate 	if (l1 == NULL)
18477c478bd9Sstevel@tonic-gate 		return (l2);
18487c478bd9Sstevel@tonic-gate 	if (l2 == NULL)
18497c478bd9Sstevel@tonic-gate 		return (l1);
18507c478bd9Sstevel@tonic-gate 
18517c478bd9Sstevel@tonic-gate 	/*
18527c478bd9Sstevel@tonic-gate 	 * in this while loop, just mark isduplicate field of node in the
18537c478bd9Sstevel@tonic-gate 	 * l2 list if the same msgid exists in l1 list.
18547c478bd9Sstevel@tonic-gate 	 */
18557c478bd9Sstevel@tonic-gate 	p = l2;
18567c478bd9Sstevel@tonic-gate 	while (p != NULL) {
18577c478bd9Sstevel@tonic-gate 		q = l1;
18587c478bd9Sstevel@tonic-gate 		while (q != NULL) {
18597c478bd9Sstevel@tonic-gate 			if (msgidcmp(p->msgid, q->msgid) == 0) {
18607c478bd9Sstevel@tonic-gate 				p->isduplicate = TRUE;
18617c478bd9Sstevel@tonic-gate 				break;
18627c478bd9Sstevel@tonic-gate 			}
18637c478bd9Sstevel@tonic-gate 			q = q->next;
18647c478bd9Sstevel@tonic-gate 		}
18657c478bd9Sstevel@tonic-gate 		p = p->next;
18667c478bd9Sstevel@tonic-gate 	}
18677c478bd9Sstevel@tonic-gate 
18687c478bd9Sstevel@tonic-gate 	/* Now connect two linked lists. */
18697c478bd9Sstevel@tonic-gate 	l1_tail = l1;
18707c478bd9Sstevel@tonic-gate 	while (l1_tail->next != NULL) {
18717c478bd9Sstevel@tonic-gate 		if (l1->next == NULL)
18727c478bd9Sstevel@tonic-gate 			break;
18737c478bd9Sstevel@tonic-gate 		l1_tail = l1_tail-> next;
18747c478bd9Sstevel@tonic-gate 	}
18757c478bd9Sstevel@tonic-gate 	l1_tail->next = l2;
18767c478bd9Sstevel@tonic-gate 
18777c478bd9Sstevel@tonic-gate 	return (l1);
18787c478bd9Sstevel@tonic-gate } /* append_list */
18797c478bd9Sstevel@tonic-gate 
18807c478bd9Sstevel@tonic-gate /*
18817c478bd9Sstevel@tonic-gate  * Writes one domain list to the file.
18827c478bd9Sstevel@tonic-gate  */
18837c478bd9Sstevel@tonic-gate static void
write_one_file(struct domain_st * head)18847c478bd9Sstevel@tonic-gate write_one_file(struct domain_st *head)
18857c478bd9Sstevel@tonic-gate {
18867c478bd9Sstevel@tonic-gate 	FILE			*fp;
18877c478bd9Sstevel@tonic-gate 	char			fname [MAX_PATH_LEN];
18887c478bd9Sstevel@tonic-gate 	char			dname [MAX_DOMAIN_LEN];
18897c478bd9Sstevel@tonic-gate 	struct element_st	*p;
18907c478bd9Sstevel@tonic-gate 	struct element_st	*existing_po_list;
18917c478bd9Sstevel@tonic-gate 
18927c478bd9Sstevel@tonic-gate 	/*
18937c478bd9Sstevel@tonic-gate 	 * If head is NULL, then it still has to create .po file
18947c478bd9Sstevel@tonic-gate 	 * so that it will guarantee that the previous .po file was
18957c478bd9Sstevel@tonic-gate 	 * alwasys deleted.
18967c478bd9Sstevel@tonic-gate 	 * This is why checking NULL pointer has been moved to after
18977c478bd9Sstevel@tonic-gate 	 * creating  .po file.
18987c478bd9Sstevel@tonic-gate 	 */
18997c478bd9Sstevel@tonic-gate 
19007c478bd9Sstevel@tonic-gate 	/*
19017c478bd9Sstevel@tonic-gate 	 * If domain name is NULL, it is the default domain list.
19027c478bd9Sstevel@tonic-gate 	 * The domain name is either "messages" or specified by option -d.
19037c478bd9Sstevel@tonic-gate 	 * The default domain name is contained in default_domain variable.
19047c478bd9Sstevel@tonic-gate 	 */
1905*df69b316SToomas Soome 	dname[0] = '\0';
19067c478bd9Sstevel@tonic-gate 	if ((head != NULL) &&
19077c478bd9Sstevel@tonic-gate 	    (head->dname != NULL)) {
19087c478bd9Sstevel@tonic-gate 		(void) strcpy(dname, head->dname);
19097c478bd9Sstevel@tonic-gate 	} else {
19107c478bd9Sstevel@tonic-gate 		(void) strcpy(dname, default_domain);
19117c478bd9Sstevel@tonic-gate 	}
19127c478bd9Sstevel@tonic-gate 
19137c478bd9Sstevel@tonic-gate 	/*
19147c478bd9Sstevel@tonic-gate 	 * path is the current directory if not specified by option -p.
19157c478bd9Sstevel@tonic-gate 	 */
19167c478bd9Sstevel@tonic-gate 	fname[0] = 0;
19177c478bd9Sstevel@tonic-gate 	if (pflg == TRUE) {
19187c478bd9Sstevel@tonic-gate 		(void) strcat(fname, pathname);
19197c478bd9Sstevel@tonic-gate 		(void) strcat(fname, "/");
19207c478bd9Sstevel@tonic-gate 	}
19217c478bd9Sstevel@tonic-gate 	(void) strcat(fname, dname);
19227c478bd9Sstevel@tonic-gate 	(void) strcat(fname, ".po");
19237c478bd9Sstevel@tonic-gate 
19247c478bd9Sstevel@tonic-gate 	/*
19257c478bd9Sstevel@tonic-gate 	 * If -j flag is specified, read exsiting .po file and
19267c478bd9Sstevel@tonic-gate 	 * append the current list to the end of the list read from
19277c478bd9Sstevel@tonic-gate 	 * the existing .po file.
19287c478bd9Sstevel@tonic-gate 	 */
19297c478bd9Sstevel@tonic-gate 	if (jflg == TRUE) {
19307c478bd9Sstevel@tonic-gate 		/*
19317c478bd9Sstevel@tonic-gate 		 * If head is NULL, we don't have to change existing file.
19327c478bd9Sstevel@tonic-gate 		 * Therefore, just return it.
19337c478bd9Sstevel@tonic-gate 		 */
19347c478bd9Sstevel@tonic-gate 		if (head == NULL) {
19357c478bd9Sstevel@tonic-gate 			return;
19367c478bd9Sstevel@tonic-gate 		}
19377c478bd9Sstevel@tonic-gate 		existing_po_list = read_po(fname);
19387c478bd9Sstevel@tonic-gate 		head->gettext_head = append_list(existing_po_list,
1939*df69b316SToomas Soome 		    head->gettext_head);
19407c478bd9Sstevel@tonic-gate #ifdef DEBUG
19417c478bd9Sstevel@tonic-gate 		if (head->dname != NULL) {
19427c478bd9Sstevel@tonic-gate 			printf("===after merge (-j option): <%s>===\n",
1943*df69b316SToomas Soome 			    head->dname);
19447c478bd9Sstevel@tonic-gate 		} else {
19457c478bd9Sstevel@tonic-gate 			printf("===after merge (-j option): <NULL>===\n");
19467c478bd9Sstevel@tonic-gate 		}
19477c478bd9Sstevel@tonic-gate 		print_one_domain(head);
19487c478bd9Sstevel@tonic-gate #endif
19497c478bd9Sstevel@tonic-gate 
19507c478bd9Sstevel@tonic-gate 	} /* if jflg */
19517c478bd9Sstevel@tonic-gate 
19527c478bd9Sstevel@tonic-gate 	if ((fp = fopen(fname, "w")) == NULL) {
19537c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
1954*df69b316SToomas Soome 		    "ERROR, can't open output file: %s\n", fname);
19557c478bd9Sstevel@tonic-gate 		exit(2);
19567c478bd9Sstevel@tonic-gate 	}
19577c478bd9Sstevel@tonic-gate 
19587c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "domain \"%s\"\n", dname);
19597c478bd9Sstevel@tonic-gate 
19607c478bd9Sstevel@tonic-gate 	/* See comments above in the beginning of this function */
19617c478bd9Sstevel@tonic-gate 	if (head == NULL)
19627c478bd9Sstevel@tonic-gate 		return;
19637c478bd9Sstevel@tonic-gate 
19647c478bd9Sstevel@tonic-gate 	/*
19657c478bd9Sstevel@tonic-gate 	 * There are separate storage for textdomain() calls if
19667c478bd9Sstevel@tonic-gate 	 * -s option is used (textdomain_head linked list).
19677c478bd9Sstevel@tonic-gate 	 * Otherwise, textdomain() is mixed with gettext(0 and dgettext().
19687c478bd9Sstevel@tonic-gate 	 * If mixed, the boolean varaible istextdomain is used to see
19697c478bd9Sstevel@tonic-gate 	 * if the current node contains textdomain() or [d]gettext().
19707c478bd9Sstevel@tonic-gate 	 */
19717c478bd9Sstevel@tonic-gate 	if (sflg == TRUE) {
19727c478bd9Sstevel@tonic-gate 		p = head->textdomain_head;
19737c478bd9Sstevel@tonic-gate 		while (p != NULL) {
19747c478bd9Sstevel@tonic-gate 			/*
19757c478bd9Sstevel@tonic-gate 			 * textdomain output line already contains
19767c478bd9Sstevel@tonic-gate 			 * FIle name and line number information.
19777c478bd9Sstevel@tonic-gate 			 * Therefore, does not have to check for nflg.
19787c478bd9Sstevel@tonic-gate 			 */
19797c478bd9Sstevel@tonic-gate 			output_textdomain(fp, p);
19807c478bd9Sstevel@tonic-gate 			p = p->next;
19817c478bd9Sstevel@tonic-gate 		}
19827c478bd9Sstevel@tonic-gate 	}
19837c478bd9Sstevel@tonic-gate 
19847c478bd9Sstevel@tonic-gate 	p = head->gettext_head;
19857c478bd9Sstevel@tonic-gate 	while (p != NULL) {
19867c478bd9Sstevel@tonic-gate 
19877c478bd9Sstevel@tonic-gate 		/*
19887c478bd9Sstevel@tonic-gate 		 * Comment is printed only if -c is used and
19897c478bd9Sstevel@tonic-gate 		 * associated with gettext or dgettext.
19907c478bd9Sstevel@tonic-gate 		 * textdomain is not associated with comments.
19917c478bd9Sstevel@tonic-gate 		 * Changes:
19927c478bd9Sstevel@tonic-gate 		 *    comments should be extracted in case of -j option
19937c478bd9Sstevel@tonic-gate 		 *    because there are read from exising file.
19947c478bd9Sstevel@tonic-gate 		 */
19957c478bd9Sstevel@tonic-gate 		if (((cflg == TRUE) || (jflg == TRUE)) &&
1996*df69b316SToomas Soome 		    (p->istextdomain != TRUE)) {
19977c478bd9Sstevel@tonic-gate 			output_comment(fp, p->comment);
19987c478bd9Sstevel@tonic-gate 		}
19997c478bd9Sstevel@tonic-gate 
20007c478bd9Sstevel@tonic-gate 		/*
20017c478bd9Sstevel@tonic-gate 		 * If -n is used, then file number and line number
20027c478bd9Sstevel@tonic-gate 		 * information is printed.
20037c478bd9Sstevel@tonic-gate 		 * In case of textdomain(), this information is redundant
20047c478bd9Sstevel@tonic-gate 		 * and is not printed.
20057c478bd9Sstevel@tonic-gate 		 * If linenum is 0, it means this information has been
20067c478bd9Sstevel@tonic-gate 		 * read from existing po file and it already contains
20077c478bd9Sstevel@tonic-gate 		 * file and line number info as a comment line. So, it
20087c478bd9Sstevel@tonic-gate 		 * should not printed in such case.
20097c478bd9Sstevel@tonic-gate 		 */
20107c478bd9Sstevel@tonic-gate 		if ((nflg == TRUE) && (p->istextdomain == FALSE) &&
2011*df69b316SToomas Soome 		    (p->linenum > 0)) {
20127c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "# File:%s, line:%d\n",
2013*df69b316SToomas Soome 			    p->fname, p->linenum);
20147c478bd9Sstevel@tonic-gate 		}
20157c478bd9Sstevel@tonic-gate 
20167c478bd9Sstevel@tonic-gate 		/*
20177c478bd9Sstevel@tonic-gate 		 * Depending on the type of node, output textdomain comment
20187c478bd9Sstevel@tonic-gate 		 * or msgid.
20197c478bd9Sstevel@tonic-gate 		 */
20207c478bd9Sstevel@tonic-gate 		if ((sflg == FALSE) &&
20217c478bd9Sstevel@tonic-gate 		    (p->istextdomain == TRUE)) {
20227c478bd9Sstevel@tonic-gate 			output_textdomain(fp, p);
20237c478bd9Sstevel@tonic-gate 		} else {
20247c478bd9Sstevel@tonic-gate 			output_msgid(fp, p->msgid, p->isduplicate);
20257c478bd9Sstevel@tonic-gate 		}
20267c478bd9Sstevel@tonic-gate 		p = p->next;
20277c478bd9Sstevel@tonic-gate 
20287c478bd9Sstevel@tonic-gate 	} /* while */
20297c478bd9Sstevel@tonic-gate 
20307c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
20317c478bd9Sstevel@tonic-gate } /* write_one_file */
20327c478bd9Sstevel@tonic-gate 
20337c478bd9Sstevel@tonic-gate /*
20347c478bd9Sstevel@tonic-gate  * Prints out textdomain call as a comment line with file name and
20357c478bd9Sstevel@tonic-gate  * the line number information.
20367c478bd9Sstevel@tonic-gate  */
20377c478bd9Sstevel@tonic-gate static void
output_textdomain(FILE * fp,struct element_st * p)20387c478bd9Sstevel@tonic-gate output_textdomain(FILE *fp, struct element_st *p)
20397c478bd9Sstevel@tonic-gate {
20407c478bd9Sstevel@tonic-gate 
20417c478bd9Sstevel@tonic-gate 	if (p == NULL)
20427c478bd9Sstevel@tonic-gate 		return;
20437c478bd9Sstevel@tonic-gate 
20447c478bd9Sstevel@tonic-gate 	/*
20457c478bd9Sstevel@tonic-gate 	 * Write textdomain() line as a comment.
20467c478bd9Sstevel@tonic-gate 	 */
20477c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "# File:%s, line:%d, textdomain(\"%s\");\n",
2048*df69b316SToomas Soome 	    p->fname, p->linenum,  p->msgid->str);
20497c478bd9Sstevel@tonic-gate } /* output_textdomain */
20507c478bd9Sstevel@tonic-gate 
20517c478bd9Sstevel@tonic-gate /*
20527c478bd9Sstevel@tonic-gate  * Prints out comments from linked list.
20537c478bd9Sstevel@tonic-gate  */
20547c478bd9Sstevel@tonic-gate static void
output_comment(FILE * fp,struct strlist_st * p)20557c478bd9Sstevel@tonic-gate output_comment(FILE *fp, struct strlist_st *p)
20567c478bd9Sstevel@tonic-gate {
20577c478bd9Sstevel@tonic-gate 	if (p == NULL)
20587c478bd9Sstevel@tonic-gate 		return;
20597c478bd9Sstevel@tonic-gate 
20607c478bd9Sstevel@tonic-gate 	/*
20617c478bd9Sstevel@tonic-gate 	 * Write comment section.
20627c478bd9Sstevel@tonic-gate 	 */
20637c478bd9Sstevel@tonic-gate 	while (p != NULL) {
20647c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "# %s\n", p->str);
20657c478bd9Sstevel@tonic-gate 		p = p->next;
20667c478bd9Sstevel@tonic-gate 	}
20677c478bd9Sstevel@tonic-gate } /* output_comment */
20687c478bd9Sstevel@tonic-gate 
20697c478bd9Sstevel@tonic-gate /*
20707c478bd9Sstevel@tonic-gate  * Prints out msgid along with msgstr.
20717c478bd9Sstevel@tonic-gate  */
20727c478bd9Sstevel@tonic-gate static void
output_msgid(FILE * fp,struct strlist_st * p,int duplicate)20737c478bd9Sstevel@tonic-gate output_msgid(FILE *fp, struct strlist_st *p, int duplicate)
20747c478bd9Sstevel@tonic-gate {
20757c478bd9Sstevel@tonic-gate 	struct strlist_st	*q;
20767c478bd9Sstevel@tonic-gate 
20777c478bd9Sstevel@tonic-gate 	if (p == NULL)
20787c478bd9Sstevel@tonic-gate 		return;
20797c478bd9Sstevel@tonic-gate 
20807c478bd9Sstevel@tonic-gate 	/*
20817c478bd9Sstevel@tonic-gate 	 * Write msgid section.
20827c478bd9Sstevel@tonic-gate 	 * If duplciate flag is ON, prepend "# " in front of every line
20837c478bd9Sstevel@tonic-gate 	 * so that they are considered as comment lines in .po file.
20847c478bd9Sstevel@tonic-gate 	 */
20857c478bd9Sstevel@tonic-gate 	if (duplicate == TRUE) {
20867c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "# ");
20877c478bd9Sstevel@tonic-gate 	}
20887c478bd9Sstevel@tonic-gate 	(void) fprintf(fp, "msgid  \"%s\"\n", p->str);
20897c478bd9Sstevel@tonic-gate 	q = p->next;
20907c478bd9Sstevel@tonic-gate 	while (q != NULL) {
20917c478bd9Sstevel@tonic-gate 		if (duplicate == TRUE) {
20927c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "# ");
20937c478bd9Sstevel@tonic-gate 		}
20947c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "       \"%s\"\n", q->str);
20957c478bd9Sstevel@tonic-gate 		q = q->next;
20967c478bd9Sstevel@tonic-gate 	}
20977c478bd9Sstevel@tonic-gate 
20987c478bd9Sstevel@tonic-gate 	/*
20997c478bd9Sstevel@tonic-gate 	 * Write msgstr section.
21007c478bd9Sstevel@tonic-gate 	 * if -M option is specified, append <suffix> to msgid.
21017c478bd9Sstevel@tonic-gate 	 * if -m option is specified, prepend <prefix> to msgid.
21027c478bd9Sstevel@tonic-gate 	 */
21037c478bd9Sstevel@tonic-gate 	if (duplicate == TRUE) {
21047c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "# ");
21057c478bd9Sstevel@tonic-gate 	}
21067c478bd9Sstevel@tonic-gate 	if ((mflg == TRUE) || (Mflg == TRUE)) {
21077c478bd9Sstevel@tonic-gate 		if (mflg == TRUE) {
21087c478bd9Sstevel@tonic-gate 			/*
21097c478bd9Sstevel@tonic-gate 			 * If single line msgid, add suffix to the same line
21107c478bd9Sstevel@tonic-gate 			 */
21117c478bd9Sstevel@tonic-gate 			if ((Mflg == TRUE) && (p->next == NULL)) {
21127c478bd9Sstevel@tonic-gate 				/* -M and -m and single line case */
2113*df69b316SToomas Soome 				(void) fprintf(fp, "msgstr \"%s%s%s\"\n",
2114*df69b316SToomas Soome 				    prefix, p->str, suffix);
21157c478bd9Sstevel@tonic-gate 			} else {
21167c478bd9Sstevel@tonic-gate 				/* -M and -m and multi line case */
2117*df69b316SToomas Soome 				(void) fprintf(fp, "msgstr \"%s%s\"\n",
2118*df69b316SToomas Soome 				    prefix, p->str);
21197c478bd9Sstevel@tonic-gate 			}
21207c478bd9Sstevel@tonic-gate 		} else {
21217c478bd9Sstevel@tonic-gate 			if ((Mflg == TRUE) && (p->next == NULL)) {
21227c478bd9Sstevel@tonic-gate 				/* -M only with single line case */
21237c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "msgstr \"%s%s\"\n",
2124*df69b316SToomas Soome 				    p->str, suffix);
21257c478bd9Sstevel@tonic-gate 			} else {
21267c478bd9Sstevel@tonic-gate 				/* -M only with multi line case */
21277c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "msgstr \"%s\"\n", p->str);
21287c478bd9Sstevel@tonic-gate 			}
21297c478bd9Sstevel@tonic-gate 		}
21307c478bd9Sstevel@tonic-gate 		q = p->next;
21317c478bd9Sstevel@tonic-gate 		while (q != NULL) {
21327c478bd9Sstevel@tonic-gate 			if (duplicate == TRUE) {
21337c478bd9Sstevel@tonic-gate 				(void) fprintf(fp, "# ");
21347c478bd9Sstevel@tonic-gate 			}
21357c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "       \"%s\"\n", q->str);
21367c478bd9Sstevel@tonic-gate 			q = q->next;
21377c478bd9Sstevel@tonic-gate 		}
21387c478bd9Sstevel@tonic-gate 		/*
21397c478bd9Sstevel@tonic-gate 		 * If multi line msgid, add suffix after the last line.
21407c478bd9Sstevel@tonic-gate 		 */
21417c478bd9Sstevel@tonic-gate 		if ((Mflg == TRUE) && (p->next != NULL) &&
2142*df69b316SToomas Soome 		    (suffix[0] != '\0')) {
21437c478bd9Sstevel@tonic-gate 			(void) fprintf(fp, "       \"%s\"\n", suffix);
21447c478bd9Sstevel@tonic-gate 		}
21457c478bd9Sstevel@tonic-gate 	} else {
21467c478bd9Sstevel@tonic-gate 		(void) fprintf(fp, "msgstr\n");
21477c478bd9Sstevel@tonic-gate 	}
21487c478bd9Sstevel@tonic-gate } /* output_msgid */
21497c478bd9Sstevel@tonic-gate 
21507c478bd9Sstevel@tonic-gate /*
21517c478bd9Sstevel@tonic-gate  * Malloc a new element node and initialize fields.
21527c478bd9Sstevel@tonic-gate  */
21537c478bd9Sstevel@tonic-gate static struct element_st *
new_element(void)21547c478bd9Sstevel@tonic-gate new_element(void)
21557c478bd9Sstevel@tonic-gate {
21567c478bd9Sstevel@tonic-gate 	struct element_st *tmp;
21577c478bd9Sstevel@tonic-gate 
21587c478bd9Sstevel@tonic-gate 	tmp = (struct element_st *)malloc(sizeof (struct element_st));
21597c478bd9Sstevel@tonic-gate 	tmp->istextdomain = FALSE;
21607c478bd9Sstevel@tonic-gate 	tmp->isduplicate = FALSE;
21617c478bd9Sstevel@tonic-gate 	tmp->msgid = NULL;
21627c478bd9Sstevel@tonic-gate 	tmp->msgstr = NULL;
21637c478bd9Sstevel@tonic-gate 	tmp->comment = NULL;
21647c478bd9Sstevel@tonic-gate 	tmp->fname = NULL;
21657c478bd9Sstevel@tonic-gate 	tmp->linenum = 0;
21667c478bd9Sstevel@tonic-gate 	tmp->next = NULL;
21677c478bd9Sstevel@tonic-gate 
21687c478bd9Sstevel@tonic-gate 	return (tmp);
21697c478bd9Sstevel@tonic-gate } /* new_element */
21707c478bd9Sstevel@tonic-gate 
21717c478bd9Sstevel@tonic-gate /*
21727c478bd9Sstevel@tonic-gate  * Malloc a new domain node and initialize fields.
21737c478bd9Sstevel@tonic-gate  */
21747c478bd9Sstevel@tonic-gate static struct domain_st *
new_domain(void)21757c478bd9Sstevel@tonic-gate new_domain(void)
21767c478bd9Sstevel@tonic-gate {
21777c478bd9Sstevel@tonic-gate 	struct domain_st *tmp;
21787c478bd9Sstevel@tonic-gate 
21797c478bd9Sstevel@tonic-gate 	tmp = (struct domain_st *)malloc(sizeof (struct domain_st));
21807c478bd9Sstevel@tonic-gate 	tmp->dname = NULL;
21817c478bd9Sstevel@tonic-gate 	tmp->gettext_head = NULL;
21827c478bd9Sstevel@tonic-gate 	tmp->gettext_tail = NULL;
21837c478bd9Sstevel@tonic-gate 	tmp->textdomain_head = NULL;
21847c478bd9Sstevel@tonic-gate 	tmp->textdomain_tail = NULL;
21857c478bd9Sstevel@tonic-gate 	tmp->next = NULL;
21867c478bd9Sstevel@tonic-gate 
21877c478bd9Sstevel@tonic-gate 	return (tmp);
21887c478bd9Sstevel@tonic-gate } /* new_domain */
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate /*
21917c478bd9Sstevel@tonic-gate  * Malloc a new string list node and initialize fields.
21927c478bd9Sstevel@tonic-gate  */
21937c478bd9Sstevel@tonic-gate static struct strlist_st *
new_strlist(void)21947c478bd9Sstevel@tonic-gate new_strlist(void)
21957c478bd9Sstevel@tonic-gate {
21967c478bd9Sstevel@tonic-gate 	struct strlist_st *tmp;
21977c478bd9Sstevel@tonic-gate 
21987c478bd9Sstevel@tonic-gate 	tmp = (struct strlist_st *)malloc(sizeof (struct strlist_st));
21997c478bd9Sstevel@tonic-gate 	tmp->str = NULL;
22007c478bd9Sstevel@tonic-gate 	tmp->next = NULL;
22017c478bd9Sstevel@tonic-gate 
22027c478bd9Sstevel@tonic-gate 	return (tmp);
22037c478bd9Sstevel@tonic-gate } /* new_strlist */
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate /*
22067c478bd9Sstevel@tonic-gate  * Malloc a new exclude string list node and initialize fields.
22077c478bd9Sstevel@tonic-gate  */
22087c478bd9Sstevel@tonic-gate static struct exclude_st *
new_exclude(void)22097c478bd9Sstevel@tonic-gate new_exclude(void)
22107c478bd9Sstevel@tonic-gate {
22117c478bd9Sstevel@tonic-gate 	struct exclude_st *tmp;
22127c478bd9Sstevel@tonic-gate 
22137c478bd9Sstevel@tonic-gate 	tmp = (struct exclude_st *)malloc(sizeof (struct exclude_st));
22147c478bd9Sstevel@tonic-gate 	tmp->exstr = NULL;
22157c478bd9Sstevel@tonic-gate 	tmp->next = NULL;
22167c478bd9Sstevel@tonic-gate 
22177c478bd9Sstevel@tonic-gate 	return (tmp);
22187c478bd9Sstevel@tonic-gate } /* new_exclude */
22197c478bd9Sstevel@tonic-gate 
22207c478bd9Sstevel@tonic-gate /*
22217c478bd9Sstevel@tonic-gate  * Local version of strcat to keep within maximum string size.
22227c478bd9Sstevel@tonic-gate  */
22237c478bd9Sstevel@tonic-gate static void
lstrcat(char * s1,const char * s2)22247c478bd9Sstevel@tonic-gate lstrcat(char *s1, const char *s2)
22257c478bd9Sstevel@tonic-gate {
22267c478bd9Sstevel@tonic-gate 	char	*es1 = &s1[MAX_STRING_LEN];
22277c478bd9Sstevel@tonic-gate 	char	*ss1 = s1;
22287c478bd9Sstevel@tonic-gate 
22297c478bd9Sstevel@tonic-gate 	while (*s1++)
22307c478bd9Sstevel@tonic-gate 		;
22317c478bd9Sstevel@tonic-gate 	--s1;
22327c478bd9Sstevel@tonic-gate 	while (*s1++ = *s2++)
22337c478bd9Sstevel@tonic-gate 		if (s1 >= es1) {
22347c478bd9Sstevel@tonic-gate 			s1[-1] = '\0';
22357c478bd9Sstevel@tonic-gate 			if ((in_comment == TRUE || in_quote == TRUE) &&
22367c478bd9Sstevel@tonic-gate 			    (warn_linenum != curr_linenum)) {
22377c478bd9Sstevel@tonic-gate 				if (stdin_only == FALSE) {
22387c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
22397c478bd9Sstevel@tonic-gate 					    "WARNING: file %s line %d exceeds "\
22407c478bd9Sstevel@tonic-gate 					    "%d characters:  \"%15.15s\"\n",
22417c478bd9Sstevel@tonic-gate 					    curr_file, curr_linenum,
22427c478bd9Sstevel@tonic-gate 					    MAX_STRING_LEN, ss1);
22437c478bd9Sstevel@tonic-gate 				} else {
22447c478bd9Sstevel@tonic-gate 					(void) fprintf(stderr,
22457c478bd9Sstevel@tonic-gate 					    "WARNING: line %d exceeds "\
22467c478bd9Sstevel@tonic-gate 					    "%d characters:  \"%15.15s\"\n",
22477c478bd9Sstevel@tonic-gate 					    curr_linenum, MAX_STRING_LEN, ss1);
22487c478bd9Sstevel@tonic-gate 				}
22497c478bd9Sstevel@tonic-gate 				warn_linenum = curr_linenum;
22507c478bd9Sstevel@tonic-gate 			}
22517c478bd9Sstevel@tonic-gate 			break;
22527c478bd9Sstevel@tonic-gate 		}
22537c478bd9Sstevel@tonic-gate } /* lstrcat */
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate #ifdef DEBUG
22567c478bd9Sstevel@tonic-gate /*
22577c478bd9Sstevel@tonic-gate  * Debug print routine. Compiled only with DEBUG on.
22587c478bd9Sstevel@tonic-gate  */
22597c478bd9Sstevel@tonic-gate void
print_element_list(struct element_st * q)22607c478bd9Sstevel@tonic-gate print_element_list(struct element_st *q)
22617c478bd9Sstevel@tonic-gate {
22627c478bd9Sstevel@tonic-gate 	struct strlist_st	*r;
22637c478bd9Sstevel@tonic-gate 
22647c478bd9Sstevel@tonic-gate 	while (q != NULL) {
22657c478bd9Sstevel@tonic-gate 		printf("   istextdomain = %d\n", q->istextdomain);
22667c478bd9Sstevel@tonic-gate 		printf("   isduplicate  = %d\n", q->isduplicate);
22677c478bd9Sstevel@tonic-gate 		if ((q->msgid != NULL) && (q->msgid->str != NULL)) {
22687c478bd9Sstevel@tonic-gate 			printf("   msgid = <%s>\n", q->msgid->str);
22697c478bd9Sstevel@tonic-gate 			r = q->msgid->next;
22707c478bd9Sstevel@tonic-gate 			while (r != NULL) {
22717c478bd9Sstevel@tonic-gate 				printf("           <%s>\n", r->str);
22727c478bd9Sstevel@tonic-gate 				r = r->next;
22737c478bd9Sstevel@tonic-gate 			}
22747c478bd9Sstevel@tonic-gate 		} else {
22757c478bd9Sstevel@tonic-gate 			printf("   msgid = <NULL>\n");
22767c478bd9Sstevel@tonic-gate 		}
22777c478bd9Sstevel@tonic-gate 		if ((q->msgstr != NULL) && (q->msgstr->str != NULL)) {
22787c478bd9Sstevel@tonic-gate 			printf("   msgstr= <%s>\n", q->msgstr->str);
22797c478bd9Sstevel@tonic-gate 			r = q->msgstr->next;
22807c478bd9Sstevel@tonic-gate 			while (r != NULL) {
22817c478bd9Sstevel@tonic-gate 				printf("           <%s>\n", r->str);
22827c478bd9Sstevel@tonic-gate 				r = r->next;
22837c478bd9Sstevel@tonic-gate 			}
22847c478bd9Sstevel@tonic-gate 		} else {
22857c478bd9Sstevel@tonic-gate 			printf("   msgstr= <NULL>\n");
22867c478bd9Sstevel@tonic-gate 		}
22877c478bd9Sstevel@tonic-gate 
22887c478bd9Sstevel@tonic-gate 		if (q->comment == NULL) {
22897c478bd9Sstevel@tonic-gate 			printf("   comment = <NULL>\n");
22907c478bd9Sstevel@tonic-gate 		} else {
22917c478bd9Sstevel@tonic-gate 			printf("   comment = <%s>\n", q->comment->str);
22927c478bd9Sstevel@tonic-gate 			r = q->comment->next;
22937c478bd9Sstevel@tonic-gate 			while (r != NULL) {
22947c478bd9Sstevel@tonic-gate 				printf("             <%s>\n", r->str);
22957c478bd9Sstevel@tonic-gate 				r = r->next;
22967c478bd9Sstevel@tonic-gate 			}
22977c478bd9Sstevel@tonic-gate 		}
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate 		if (q->fname == NULL) {
23007c478bd9Sstevel@tonic-gate 			printf("   fname = <NULL>\n");
23017c478bd9Sstevel@tonic-gate 		} else {
23027c478bd9Sstevel@tonic-gate 			printf("   fname = <%s>\n", q->fname);
23037c478bd9Sstevel@tonic-gate 		}
23047c478bd9Sstevel@tonic-gate 		printf("   linenum = %d\n", q->linenum);
23057c478bd9Sstevel@tonic-gate 		printf("\n");
23067c478bd9Sstevel@tonic-gate 		q = q->next;
23077c478bd9Sstevel@tonic-gate 	}
23087c478bd9Sstevel@tonic-gate }
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate /*
23117c478bd9Sstevel@tonic-gate  * Debug print routine. Compiled only with DEBUG on.
23127c478bd9Sstevel@tonic-gate  */
23137c478bd9Sstevel@tonic-gate void
print_one_domain(struct domain_st * p)23147c478bd9Sstevel@tonic-gate print_one_domain(struct domain_st *p)
23157c478bd9Sstevel@tonic-gate {
23167c478bd9Sstevel@tonic-gate 	struct element_st	*q;
23177c478bd9Sstevel@tonic-gate 
23187c478bd9Sstevel@tonic-gate 	if (p == NULL) {
23197c478bd9Sstevel@tonic-gate 		printf("domain pointer = <NULL>\n");
23207c478bd9Sstevel@tonic-gate 		return;
23217c478bd9Sstevel@tonic-gate 	} else if (p->dname == NULL) {
23227c478bd9Sstevel@tonic-gate 		printf("domain_name = <%s>\n", "<NULL>");
23237c478bd9Sstevel@tonic-gate 	} else {
23247c478bd9Sstevel@tonic-gate 		printf("domain_name = <%s>\n", p->dname);
23257c478bd9Sstevel@tonic-gate 	}
23267c478bd9Sstevel@tonic-gate 	q = p->gettext_head;
23277c478bd9Sstevel@tonic-gate 	print_element_list(q);
23287c478bd9Sstevel@tonic-gate 
23297c478bd9Sstevel@tonic-gate 	q = p->textdomain_head;
23307c478bd9Sstevel@tonic-gate 	print_element_list(q);
23317c478bd9Sstevel@tonic-gate } /* print_one_domain */
23327c478bd9Sstevel@tonic-gate 
23337c478bd9Sstevel@tonic-gate void
print_all_domain(struct domain_st * dom_list)23347c478bd9Sstevel@tonic-gate print_all_domain(struct domain_st *dom_list)
23357c478bd9Sstevel@tonic-gate {
23367c478bd9Sstevel@tonic-gate 	struct domain_st	*p;
23377c478bd9Sstevel@tonic-gate 	struct element_st	*q;
23387c478bd9Sstevel@tonic-gate 
23397c478bd9Sstevel@tonic-gate 	p = dom_list;
23407c478bd9Sstevel@tonic-gate 	while (p != NULL) {
23417c478bd9Sstevel@tonic-gate 		print_one_domain(p);
23427c478bd9Sstevel@tonic-gate 		p = p->next;
23437c478bd9Sstevel@tonic-gate 	} /* while */
23447c478bd9Sstevel@tonic-gate } /* print_all_domain */
23457c478bd9Sstevel@tonic-gate #endif
2346