/* $Copyright:	$
 * Copyright (c) 1984, 1985, 1986, 1987, 1988, 1989, 1990 
 * Sequent Computer Systems, Inc.   All rights reserved.
 *  
 * This software is furnished under a license and may be used
 * only in accordance with the terms of that license and with the
 * inclusion of the above copyright notice.   This software may not
 * be provided or otherwise made available to, or used by, any
 * other person.  No title to or ownership of the software is
 * hereby transferred.
*/

/*	Copyright (c) 1986 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/



#ident	"$Header: strtows.c 1.2 90/04/21 $@(#)libw-port:wstring/strtows.c	1.0"

/*
 * Strtows transforms EUC in character string "s2" into
 * the process codes, and transfers those to wchar_t string "s1",
 * stopping after the NULL character has been processed.
 */

#include "shlib.h"
#include <widec.h>
#include <errno.h>
#include <euc.h>
#include "libw_pcode.h"
#define  NULL	0

extern void _xgetwidth();
extern int  _cswidth[];
extern eucwidth_t _eucwidth;
#define pcw	_eucwidth._pcw	/* use for checking wchar_t is 2 or 4 bytes	*/

wchar_t *
strtows(s1, s2)
register wchar_t *s1;
register char *s2;
{
	register size, temp, mask;
	register wchar_t *os1 = s1;

	if (! *_cswidth)
		_xgetwidth(); /* get character width */

	while (*s2) {
		if (! (*s2 & 0x80)) { /* Code Set 0 */
			*s1++ = *s2++;
			continue;
		}
		/*
		 * "Size" tells us how many bytes to expect following.
		 */
		temp = 0;
		switch (*s2 & 0377) {
			case SS2: /* Code Set 2 */
				if (pcw > sizeof(unsigned short))
					mask = F_P01;	/* wchar_t is long	*/
				else
					mask = P01;	/* wchar_t is short	*/
				size = _cswidth[2];
				goto testsize;
			case SS3: /* Code set 3 */
				if (pcw > sizeof(unsigned short))
					mask = F_P10;	/* wchar_t is long	*/
				else
					mask = P10;	/* wchar_t is short	*/
				size = _cswidth[3];
			testsize:
				if (size == 0) {
					*s1++ = *s2++;
					continue;
				}
				break;
			default:  /* Code Set 1 */
				if (control1(*s2 & 0377)) { /* control character 1 */
					*s1++ = *s2++;
					continue;
				}
				if (pcw > sizeof(unsigned short))
					mask = F_P11;	/* wchar_t is long	*/
				else
					mask = P11;	/* wchar_t is short	*/
				if ((size = _cswidth[1] - 1) >= 0)
					temp = (*s2 & 0177);
				else { /* EUC size is zero */
					*s1 = 0;
					errno = EILSEQ;
					return(NULL);
				}
		}
		s2++;
		/*
		 * This loop shifts previous bytes left, sticking
		 * the new byte into the low order byte of temp.
		 */
		while (size--) {
			if (!graphic(*s2 & 0377)) {
				*s1 = 0;
				errno = EILSEQ;
				return(NULL);
			}
			if (pcw > sizeof(unsigned short))
				temp = ((temp << 7) | (*s2++ & 0177));
			else
				temp = ((temp << 8) | (*s2++ & 0177));
		}
		/*
		 * Mask the value so that it fits into the proper
		 * character set pattern for the high order bits
		 * of each byte:
		 *     CS0-0000  CS1=0011  CS2=0001  CS3=0010
		 */
		*s1++ = (temp | mask);
	}
	*s1 = 0;
	return(os1);
}
