line_length = PL_strlen(line);
line_length = nsCRT::strlen(line);
static int msg_parse_Header_addresses (const char *line, char **names, char **addresses,								PRBool quote_names_p, PRBool quote_addrs_p, PRBool first_only_p){	PRUint32 addr_count = 0;	size_t line_length;	const char *line_end;	const char *this_start;	char *name_buf = 0, *name_out, *name_start;	char *addr_buf = 0, *addr_out, *addr_start;	NS_ASSERTION(line, ""); 	if (!line)		return -1;	if (names)		*names = 0;	if (addresses)		*addresses = 0;	line_length = PL_strlen(line);	if (line_length == 0)		return 0;	name_buf = (char *)PR_Malloc(line_length * 2 + 10);	if (!name_buf)		return NS_ERROR_OUT_OF_MEMORY;	addr_buf = (char *)PR_Malloc(line_length * 2 + 10);	if (!addr_buf)	{		FREEIF(name_buf);		return NS_ERROR_OUT_OF_MEMORY;	}	line_end = line;	addr_out = addr_buf;	name_out = name_buf;	name_start = name_buf;	addr_start = addr_buf;	this_start = line;  	/* Skip over extra whitespace or commas before addresses.	 */	while (*line_end && (IS_SPACE(*line_end) || *line_end == ','))		NEXT_CHAR(line_end);	while (*line_end)	{		PRUint32 paren_depth = 0;		const char *oparen = 0;		const char *mailbox_start = 0;		const char *mailbox_end = 0;		while (   *line_end		       && !(   *line_end == ',' && paren_depth <= 0 /* comma is ok inside () */                    && (!mailbox_start || mailbox_end)))    /* comma is ok inside <> */		{			if (*line_end == '\\')			{				line_end++;				if (!*line_end)	/* otherwise, we walk off end of line, right? */					break;			}			else if (*line_end == '\"') 			{				int leave_quotes = 0;				line_end++;  /* remove open " */				/* handle '"John.Van Doe"@space.com' case */				if (paren_depth == 0 && !mailbox_start)				{					char *end_quote = PL_strstr(line_end, "\"");					char *mailbox   = end_quote ? PL_strstr(end_quote, "<") : (char *)NULL,					     *comma     = end_quote ? PL_strstr(end_quote, ",") : (char *)NULL;					if (!mailbox || (comma && comma < mailbox))					{						leave_quotes = 1; /* no mailbox for this address */						*addr_out++ = '\"';					}				}				while (*line_end)				{					if (*line_end == '\\')					{						if (   paren_depth == 0							&& (*(line_end+1) == '\\' || *(line_end+1) == '\"'))							*addr_out++ = *line_end++;						else							line_end++;					}					else if (*line_end == '\"')					{						line_end++;  /* remove close " */						break;					}					if (paren_depth == 0)						COPY_CHAR(addr_out, line_end);					NEXT_CHAR(line_end);				}				if (leave_quotes) *addr_out++ = '\"';				continue;			}			if (*line_end == '(')			{				if (paren_depth == 0)					oparen = line_end;				paren_depth++;			}			else if (*line_end == '<' && paren_depth == 0)			{				mailbox_start = line_end;			}			else if (*line_end == '>' && mailbox_start && paren_depth == 0)			{				mailbox_end = line_end;			}			else if (*line_end == ')' && paren_depth > 0)			{				paren_depth--;				if (paren_depth == 0)				{					const char *s = oparen + 1;					/* Copy the chars inside the parens onto the "name" buffer.					 */					/* Push out some whitespace before the paren, if					 * there is non-whitespace there already.					 */					if (name_out > name_start && !IS_SPACE(name_out [-1]))						*name_out++ = ' ';					/* Skip leading whitespace.					 */					while (IS_SPACE(*s) && s < line_end)						s++;					while (s < line_end)					{						/* Strip out " within () unless backslashed						 */						if (*s == '\"')						{							s++;							continue;						}						if (*s == '\\')	/* remove one \ */							s++;						if (IS_SPACE(*s) && name_out > name_start && IS_SPACE(name_out[-1]))							/* collapse consecutive whitespace */;						else							COPY_CHAR(name_out, s);						NEXT_CHAR(s);					}					oparen = 0;				}			}			else			{				/* If we're not inside parens or a <mailbox>, tack this				 * on to the end of the addr_buf.				 */				if (paren_depth == 0 && (!mailbox_start || mailbox_end))				{					/* Eat whitespace at the beginning of the line,					 * and eat consecutive whitespace within the line.					 */					if (   IS_SPACE(*line_end)					    && (addr_out == addr_start || IS_SPACE(addr_out[-1])))						/* skip it */;					else						COPY_CHAR(addr_out, line_end);				}			}		  	NEXT_CHAR(line_end);		}		/* Now we have extracted a single address from the comma-separated		 * list of addresses.  The characters have been divided among the		 * various buffers: the parts inside parens have been placed in the		 * name_buf, and everything else has been placed in the addr_buf.		 * Quoted strings and backslashed characters have been `expanded.'		 *		 * If there was a <mailbox> spec in it, we have remembered where it was.		 * Copy that on to the addr_buf, replacing what was there, and copy the		 * characters not inside <> onto the name_buf, replacing what is there		 * now (which was just the parenthesized parts.)  (And we need to do the		 * quote and backslash hacking again, since we're coming from the		 * original source.)		 *		 * Otherwise, we're already done - the addr_buf and name_buf contain		 * the right data already (de-quoted.)		 */		if (mailbox_end)		{			const char *s;			NS_ASSERTION(*mailbox_start == '<', "");			NS_ASSERTION(*mailbox_end == '>', "");			/* First, copy the name.			 */			name_out = name_start;			s = this_start;			/* Skip leading whitespace.			 */			while (IS_SPACE(*s) && s < mailbox_start)				s++;			/* Copy up to (not including) the <			 */			while (s < mailbox_start)			{				if (*s == '\"')				{					s++;					continue;				}				if (*s == '\\')			    {					if (s + 1 < mailbox_start && (*(s+1) == '\\' || *(s+1) == '\"'))				    	*name_out++ = *s++;					else						s++;				}				if (IS_SPACE(*s) && name_out > name_start && IS_SPACE(name_out[-1]))					/* collapse consecutive whitespace */;				else					COPY_CHAR(name_out, s);				NEXT_CHAR(s);			}			/* Push out one space.			 */			TRIM_WHITESPACE(name_start, name_out, ' ');			s = mailbox_end + 1;			/* Skip whitespace after >			 */			while (IS_SPACE(*s) && s < line_end)				s++;			/* Copy from just after > to the end.			 */			while (s < line_end)			{				if (*s == '\"')				{					s++;					continue;				}				if (*s == '\\')			    {					if (s + 1 < line_end && (*(s+1) == '\\' || *(s+1) == '\"'))				    	*name_out++ = *s++;					else						s++;				}				if (IS_SPACE (*s) && name_out > name_start && IS_SPACE (name_out[-1]))					/* collapse consecutive whitespace */;				else					COPY_CHAR(name_out, s);				NEXT_CHAR(s);			}			TRIM_WHITESPACE(name_start, name_out, 0);			/* Now, copy the address.			 */			mailbox_start++;			addr_out = addr_start;			s = mailbox_start;			/* Skip leading whitespace.			 */			while (IS_SPACE(*s) && s < mailbox_end)				s++;			/* Copy up to (not including) the >			 */			while (s < mailbox_end)			{				if (*s == '\"')				{					s++;					continue;				}				if (*s == '\\')			    {					if (s + 1 < mailbox_end && (*(s+1) == '\\' || *(s+1) == '\"'))					 	*addr_out++ = *s++;					else						s++;				}				COPY_CHAR(addr_out, s);				NEXT_CHAR(s);			}			TRIM_WHITESPACE(addr_start, addr_out, 0);		}		/* No component of <mailbox> form.		 */		else		{			TRIM_WHITESPACE(addr_start, addr_out, 0);			TRIM_WHITESPACE(name_start, name_out, 0);			/* Attempt to deal with the simple error case of a missing comma.			 * We can only really deal with this in the non-<> case.			 * If there is no name, and if the address doesn't contain			 * double-quotes, but the address does contain whitespace,			 * then assume that the whitespace is an address delimiter.			 */			if (!name_start || !*name_start)			{				char *s;				char *space = 0;				for (s = addr_start; s < addr_out; NEXT_CHAR(s))				{					if (*s == '\\')						s++;					else if (!space && IS_SPACE(*s))						space = s;					else if (*s == '\"')					{						space = 0;						break;					}				}				if (space)				{					for (s = space; s < addr_out; NEXT_CHAR(s))					{						if (*s == '\\')							s++;						else if (IS_SPACE(*s))						{							*s = 0;							*name_out++ = 0;							addr_count++;						}					}				}			}		}		/* Now re-quote the names and addresses if necessary.		 */		if (quote_names_p && names)		{			int L = name_out - name_start - 1;			L = msg_quote_phrase_or_addr(name_start, L, PR_FALSE);			name_out = name_start + L + 1;		}		if (quote_addrs_p && addresses)		{			int L = addr_out - addr_start - 1;			L = msg_quote_phrase_or_addr(addr_start, L, PR_TRUE);			addr_out = addr_start + L + 1;		}		addr_count++;		/* If we only want the first address, we can stop now.		 */		if (first_only_p)			break;		if (*line_end)			NEXT_CHAR(line_end);		/* Skip over extra whitespace or commas between addresses. */		while (*line_end && (IS_SPACE(*line_end) || *line_end == ','))			line_end++;		this_start = line_end;		name_start = name_out;		addr_start = addr_out;	}	/* Make one more pass through and convert all whitespace characters	 * to SPC.  We could do that in the first pass, but this is simpler.	 */	{		char *s;		for (s = name_buf; s < name_out; NEXT_CHAR(s))			if (IS_SPACE(*s) && *s != ' ')				*s = ' ';		for (s = addr_buf; s < addr_out; NEXT_CHAR(s))			if (IS_SPACE(*s) && *s != ' ')				*s = ' ';	}	if (names)		*names = name_buf;	else		PR_Free(name_buf);	if (addresses)		*addresses = addr_buf;	else		PR_Free(addr_buf);	return addr_count;}