/* $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) 1988 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: mbstowcs.c 1.5 90/09/07 $@(#)libc-port:locale/mbstowcs.c 1.0 AT&T-UP"

/*
 * mbstowcs.c
 * 30/6/88
 * UEL
 */

#include <ctype.h>
#include <stdlib.h>
#include <sys/types.h>
#define SS2     0x8e
#define SS3     0x8f
/*
 *	The followings are for 4 bytes of multi-byte code definition.
 */
#define EUCMASK 0x30000000
#define P00     0x00000000    /* Code Set 0 */
#define P11     0x30000000    /* Code Set 1 */
#define P01     0x10000000    /* Code Set 2 */
#define P10     0x20000000    /* Code Set 3 */
/*
 *	The followings are for 2 bytes of multi-byte code definition.
 */
#define H_P11     0x8080	/* Code Set 1 for 2 bytes code */
#define H_P01     0x0080	/* Code Set 2 for 2 bytes code */
#define H_P10     0x8000	/* Code Set 3 for 2 bytes code */

#define multibyte       (_ctype[520]>1)
#define eucw1   _ctype[514]
#define eucw2   _ctype[515]
#define eucw3   _ctype[516]

int mbstowcs(wchar, s, n)
wchar_t     *wchar;
char               *s;
size_t                 n;
{
    register int length;
    register wchar_t intcode;
    register c;
    wchar_t mask, mask01, mask10, mask11;
    int size, pcw;
        
        if(s == (char *)0)
                return 0;

        if(n <= 0)
                return(-1);

	if ( eucw1 > sizeof(unsigned short) ||
	     eucw2 > sizeof(unsigned short) ||
	     eucw3 > sizeof(unsigned short)) {
		pcw = sizeof(unsigned long);	/* 32 bits process code */
		mask01 = P01;
		mask10 = P10;
		mask11 = P11;
	}
	else {
		pcw = sizeof(unsigned short);	/* 16 bits process code */
		mask01 = H_P01;
		mask10 = H_P10;
		mask11 = H_P11;
	}

        size = 0;
        while (n-- > 0) {
                c = (unsigned char)*s++;
                intcode = 0;
                length = 0;
                mask = 0;
                if (!multibyte || c < 0200) 
                        intcode = c; 
                else
                if (c == SS2) {
                        if((length = eucw2)) 
                                mask = mask01;
                } else
                if (c == SS3) {
                        if((length = eucw3)) 
                                mask = mask10;
                } else 			     /* MNLS defines space as cntrl */
                if ((iscntrl(c & 0177)) || ((c & 0177) == 040))
                        intcode = c;
                else {
                        length = eucw1-1;
                        mask = mask11;
                        intcode = c & 0177;
                }
                size++;
                if(length) {
                        if ( (n-length-1) < 0) {
                                *wchar = 0;
                                return size;
                        }		     /* MNLS defines space as cntrl */ 
			if(pcw > sizeof(unsigned short)) {
                        	while(length--) {
                                	if(((c=(unsigned char)*s++) < 0200)
							|| (iscntrl(c & 0177))
							|| ((c & 0177) == 040))
                                        	return(-1);

                                	intcode = (intcode << 7) | (c & 0177);
                        	}
			}
			else {		     /* MNLS defines space as cntrl */
                        	while(length--) {
                                	if(((c=(unsigned char)*s++) < 0200)
						         || (iscntrl(c & 0177))
							 || ((c & 0177) == 040))
                                        	return(-1);

                                	intcode = (intcode << 8) | (c & 0177);
				}
                        }
                } 
                *wchar++ = intcode | mask;
                if (intcode == 0) {
                        size--;
                        return size;
                }
        }       
        return size;
}
