/* strxtens.c (libext+gcc) -- non-Posix extensions to string.h */
/*-
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/nls.h>

#include <stringx.h>

/*
 * Get next token from string *stringp, where tokens are nonempty
 * strings separated by characters from delim.  
 *
 * Writes NULs into the string at *stringp to end tokens.
 * delim need not remain constant from call to call.
 * On return, *stringp points past the last NUL written (if there might
 * be further tokens), or is NULL (if there are definitely no more tokens).
 *
 * If *stringp is NULL, strtoken returns NULL.
 */
	extern char *
_strsep(register char **stringp, register __const__ char *delim)
{
	register char *s;
	register __const__ char *spanp;
	register int c, sc;
	char *tok;

	if ((s = *stringp) == NULL)
		return (NULL);
	for (tok = s;;) {
		c = *s++;
		spanp = delim;
		do {
			if ((sc = *spanp++) == c) {
				if (c == 0)
					s = NULL;
				else
					s[-1] = 0;
				*stringp = s;
				return (tok);
			}
		} while (sc != 0);
	}
	/* NOTREACHED */
}

/* Parts are: -- Copyright (c) 1996 by Eberhard Mattes, see Copying. */
  
  /* hackish workaround for missing dll exports from sys/nls.h; an emx bug */
	static __const__ unsigned char 		/* DBCS-support broken. Fix me! */
_nls_ctype_tab_hackish_workaround[256] = {0};

	static __inline__ __const__ unsigned char  
__strx_isDbcsLead(__const__ unsigned int c)
{
	return(_nls_ctype_tab_hackish_workaround[c]);
}

/* Detect trailing slash or backslash for stat(), access(), and
   _tmpidxnam().  If MODE is 0, the trailing (back)slash may be
   preceded by an arbitrary character, including none.  Moreover, a
   trailing colon is treated like a trailing slash.  If MODE is 1, the
   trailing (back)slash must be preceded by a character which is not a
   (back)slash or a colon.  Note that the string pointed to by NAME
   need not be null-terminated! */ /* Support only SBCS and DBCS for now. */

	extern int 
_strHasTrailingSlash(__const__ char *str, __const__ size_t len,
								__const__ int mode)
{
  switch (mode) {
    case 0:
      if (len < 1 || (str[len-1] != '\\' && str[len-1] != '/'
                      && str[len-1] != ':'))
        return 0;
      if (len == 1 && (str[0] == '\\' || str[0] == '/')) return 1;
      break;
    case 1:
      if (len < 2 || (str[len-1] != '\\' && str[len-1] != '/'))
        return 0;
      break;

    default: return 0;
  }
  /* The str seems to have a trailing (back)slash.  There are two
     conditions which must _not_ hold:

     (1) the (back)slash is the 2nd byte of a DBCS character
     (2) the (back)slash is preceded by a SBCS (back)slash or a colon

     Condition (2) does not matter if MODE is 0.

          |         |     |     | return for MODE
     Case | str(*)  | (1) | (2) |   0   |   1
     -----+---------+-----+-----+-------+-------
     (a)  | ....//  | no  | yes |   1   |   0
     (b)  | ....S/  | no  | no  |   1   |   1
     (c)  | ...L2/  | no  | no  |   1   |   1
     (d)  | ....L/  | yes | -   |   0   |   0

     (*) S = SBCS character but not a (back)slash or colon
         L = lead byte
         2 = 2nd byte of DBCS char */
 { 
  size_t i = 0;
  do {
      if (__strx_isDbcsLead((unsigned char)str[i])) {
        if (i == len - 3) { /* Case (c) -- a DBCS character precedes
						                  the trailing (back)slash. */
          return 1;
        } else 
          if (i == len - 2) { /* Case (d) -- the last byte is the 2nd byte of a 
		            DBCS character and therefore is not a SBCS (back)slash. */
            return 0;
           } else
            i += 2;
      } else 
        if (i == len - 2) { 	/* We hit the character preceding the trailing 
             		(back)slash; this is either case (a) or (b).  Check for 
             			condition (2), condition (1) does not apply. */
          return(mode == 0||(str[i] != '\\'&&str[i] != '/'&&str[i] != ':'));
        }
        else  ++i;
  } while (1);
 }
}

	extern void 
_strRemoveTrailingSlashes(char*path)
{
  register size_t
  i = strlen(path) - 1;

  for ( ; i && (path[i] == '/'||path[i] == '\\'); --i)
    path[i] = '\0';
}



/* External library versions */

	extern int 	/* Compare S and T, ignoring case. */
strcasecmp(__const__ char*s,__const__ char*t) {return _stricmp(s,t);}
	extern int /* Compare no more than N chars of S and T, ignoring case. */
memcasecmp(__const__ void*s,__const__ void*t,size_t n) {return _memicmp(s,t,n);}
	extern  int 
strncasecmp(__const__ char*s,__const__ char*t,size_t n){return _strnicmp(s,t,n);}
	extern  char *
strsep(register char **s, register __const__ char *d) {return _strsep(s,d);}

