Blame src/cmd/ksh93/sh/string.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1982-2012 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
#pragma prototyped
Packit Service a8c26c
/*
Packit Service a8c26c
 * string processing routines for Korn shell
Packit Service a8c26c
 *
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#include	<ast.h>
Packit Service a8c26c
#include	<ast_wchar.h>
Packit Service a8c26c
#include	"defs.h"
Packit Service a8c26c
#include	<stak.h>
Packit Service a8c26c
#include	<ccode.h>
Packit Service a8c26c
#include	"shtable.h"
Packit Service a8c26c
#include	"lexstates.h"
Packit Service a8c26c
#include	"national.h"
Packit Service a8c26c
Packit Service a8c26c
#if _hdr_wctype
Packit Service a8c26c
#   include <wctype.h>
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#if !_lib_iswprint && !defined(iswprint)
Packit Service a8c26c
#   define iswprint(c)		(((c)&~0377) || isprint(c))
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 *  Table lookup routine
Packit Service a8c26c
 *   is searched for string <sp> and corresponding value is returned
Packit Service a8c26c
 *  This is only used for small tables and is used to save non-sharable memory 
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
const Shtable_t *sh_locate(register const char *sp,const Shtable_t *table,int size)
Packit Service a8c26c
{
Packit Service a8c26c
	register int			first;
Packit Service a8c26c
	register const Shtable_t	*tp;
Packit Service a8c26c
	register int			c;
Packit Service a8c26c
	static const Shtable_t		empty = {0,0};
Packit Service a8c26c
	if(sp==0 || (first= *sp)==0)
Packit Service a8c26c
		return(&empty);
Packit Service a8c26c
	tp=table;
Packit Service a8c26c
	while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(first == c && strcmp(sp,tp->sh_name)==0)
Packit Service a8c26c
			return(tp);
Packit Service a8c26c
		tp = (Shtable_t*)((char*)tp+size);
Packit Service a8c26c
	}
Packit Service a8c26c
	return(&empty);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 *  shtab_options lookup routine
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#define sep(c)		((c)=='-'||(c)=='_')
Packit Service a8c26c
Packit Service a8c26c
int sh_lookopt(register const char *sp, int *invert)
Packit Service a8c26c
{
Packit Service a8c26c
	register int			first;
Packit Service a8c26c
	register const Shtable_t	*tp;
Packit Service a8c26c
	register int			c;
Packit Service a8c26c
	register const char		*s, *t, *sw, *tw;
Packit Service a8c26c
	int				amb;
Packit Service a8c26c
	int				hit;
Packit Service a8c26c
	int				inv;
Packit Service a8c26c
	int				no;
Packit Service a8c26c
	if(sp==0)
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	if(*sp=='n' && *(sp+1)=='o' && (*(sp+2)!='t' || *(sp+3)!='i'))
Packit Service a8c26c
	{
Packit Service a8c26c
		sp+=2;
Packit Service a8c26c
		if(sep(*sp))
Packit Service a8c26c
			sp++;
Packit Service a8c26c
		*invert = !*invert;
Packit Service a8c26c
	}
Packit Service a8c26c
	if((first= *sp)==0)
Packit Service a8c26c
		return(0);
Packit Service a8c26c
	tp=shtab_options;
Packit Service a8c26c
	amb=hit=0;
Packit Service a8c26c
	for(;;)
Packit Service a8c26c
	{
Packit Service a8c26c
		t=tp->sh_name;
Packit Service a8c26c
		if(no = *t=='n' && *(t+1)=='o' && *(t+2)!='t')
Packit Service a8c26c
			t+=2;
Packit Service a8c26c
		if(!(c= *t))
Packit Service a8c26c
			break;
Packit Service a8c26c
		if(first == c)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(strcmp(sp,t)==0)
Packit Service a8c26c
			{
Packit Service a8c26c
				*invert ^= no;
Packit Service a8c26c
				return(tp->sh_number);
Packit Service a8c26c
			}
Packit Service a8c26c
			s=sw=sp;
Packit Service a8c26c
			tw=t;
Packit Service a8c26c
			for(;;)
Packit Service a8c26c
			{
Packit Service a8c26c
				if(!*s || *s=='=')
Packit Service a8c26c
				{
Packit Service a8c26c
					if (*s == '=' && !strtol(s+1, NiL, 0))
Packit Service a8c26c
						no = !no;
Packit Service a8c26c
					if (!*t)
Packit Service a8c26c
					{
Packit Service a8c26c
						*invert ^= no;
Packit Service a8c26c
						return(tp->sh_number);
Packit Service a8c26c
					}
Packit Service a8c26c
					if (hit || amb)
Packit Service a8c26c
					{
Packit Service a8c26c
						hit = 0;
Packit Service a8c26c
						amb = 1;
Packit Service a8c26c
					}
Packit Service a8c26c
					else
Packit Service a8c26c
					{
Packit Service a8c26c
						hit = tp->sh_number;
Packit Service a8c26c
						inv = no;
Packit Service a8c26c
					}
Packit Service a8c26c
					break;
Packit Service a8c26c
				}
Packit Service a8c26c
				else if(!*t)
Packit Service a8c26c
					break;
Packit Service a8c26c
				else if(sep(*s))
Packit Service a8c26c
					sw = ++s;
Packit Service a8c26c
				else if(sep(*t))
Packit Service a8c26c
					tw = ++t;
Packit Service a8c26c
				else if(*s==*t)
Packit Service a8c26c
				{
Packit Service a8c26c
					s++;
Packit Service a8c26c
					t++;
Packit Service a8c26c
				}
Packit Service a8c26c
				else if(s==sw && t==tw)
Packit Service a8c26c
					break;
Packit Service a8c26c
				else
Packit Service a8c26c
				{
Packit Service a8c26c
					if(t!=tw)
Packit Service a8c26c
					{
Packit Service a8c26c
						while(*t && !sep(*t))
Packit Service a8c26c
							t++;
Packit Service a8c26c
						if(!*t)
Packit Service a8c26c
							break;
Packit Service a8c26c
						tw = ++t;
Packit Service a8c26c
					}
Packit Service a8c26c
					while (s>sw && *s!=*t)
Packit Service a8c26c
						s--;
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
		}
Packit Service a8c26c
		tp = (Shtable_t*)((char*)tp+sizeof(*shtab_options));
Packit Service a8c26c
	}
Packit Service a8c26c
	if(hit)
Packit Service a8c26c
		*invert ^= inv;
Packit Service a8c26c
	return(hit);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * look for the substring <oldsp> in <string> and replace with <newsp>
Packit Service a8c26c
 * The new string is put on top of the stack
Packit Service a8c26c
 */
Packit Service a8c26c
char *sh_substitute(const char *string,const char *oldsp,char *newsp)
Packit Service a8c26c
/*@
Packit Service a8c26c
	assume string!=NULL && oldsp!=NULL && newsp!=NULL;
Packit Service a8c26c
	return x satisfying x==NULL ||
Packit Service a8c26c
		strlen(x)==(strlen(in string)+strlen(in newsp)-strlen(in oldsp));
Packit Service a8c26c
@*/
Packit Service a8c26c
{
Packit Service a8c26c
	register const char *sp = string;
Packit Service a8c26c
	register const char *cp;
Packit Service a8c26c
	const char *savesp = 0;
Packit Service a8c26c
	stakseek(0);
Packit Service a8c26c
	if(*sp==0)
Packit Service a8c26c
		return((char*)0);
Packit Service a8c26c
	if(*(cp=oldsp) == 0)
Packit Service a8c26c
		goto found;
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
	mbinit();
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
	do
Packit Service a8c26c
	{
Packit Service a8c26c
	/* skip to first character which matches start of oldsp */
Packit Service a8c26c
		while(*sp && (savesp==sp || *sp != *cp))
Packit Service a8c26c
		{
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
			/* skip a whole character at a time */
Packit Service a8c26c
			int c = mbsize(sp);
Packit Service a8c26c
			if(c < 0)
Packit Service a8c26c
				sp++;
Packit Service a8c26c
			while(c-- > 0)
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
			stakputc(*sp++);
Packit Service a8c26c
		}
Packit Service a8c26c
		if(*sp == 0)
Packit Service a8c26c
			return((char*)0);
Packit Service a8c26c
		savesp = sp;
Packit Service a8c26c
	        for(;*cp;cp++)
Packit Service a8c26c
		{
Packit Service a8c26c
			if(*cp != *sp++)
Packit Service a8c26c
				break;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(*cp==0)
Packit Service a8c26c
		/* match found */
Packit Service a8c26c
			goto found;
Packit Service a8c26c
		sp = savesp;
Packit Service a8c26c
		cp = oldsp;
Packit Service a8c26c
	}
Packit Service a8c26c
	while(*sp);
Packit Service a8c26c
	return((char*)0);
Packit Service a8c26c
Packit Service a8c26c
found:
Packit Service a8c26c
	/* copy new */
Packit Service a8c26c
	stakputs(newsp);
Packit Service a8c26c
	/* copy rest of string */
Packit Service a8c26c
	stakputs(sp);
Packit Service a8c26c
	return(stakfreeze(1));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * TRIM(sp)
Packit Service a8c26c
 * Remove escape characters from characters in <sp> and eliminate quoted nulls.
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
void	sh_trim(register char *sp)
Packit Service a8c26c
/*@
Packit Service a8c26c
	assume sp!=NULL;
Packit Service a8c26c
	promise  strlen(in sp) <= in strlen(sp);
Packit Service a8c26c
@*/
Packit Service a8c26c
{
Packit Service a8c26c
	register char *dp;
Packit Service a8c26c
	register int c;
Packit Service a8c26c
	if(sp)
Packit Service a8c26c
	{
Packit Service a8c26c
		dp = sp;
Packit Service a8c26c
		while(c= *sp)
Packit Service a8c26c
		{
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
			int len;
Packit Service a8c26c
			if(mbwide() && (len=mbsize(sp))>1)
Packit Service a8c26c
			{
Packit Service a8c26c
				memmove(dp, sp, len);
Packit Service a8c26c
				dp += len;
Packit Service a8c26c
				sp += len;
Packit Service a8c26c
				continue;
Packit Service a8c26c
			}
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
			sp++;
Packit Service a8c26c
			if(c == '\\')
Packit Service a8c26c
				c = *sp++;
Packit Service a8c26c
			if(c)
Packit Service a8c26c
				*dp++ = c;
Packit Service a8c26c
		}
Packit Service a8c26c
		*dp = 0;
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * copy <str1> to <str2> changing upper case to lower case
Packit Service a8c26c
 * <str2> must be big enough to hold <str1>
Packit Service a8c26c
 * <str1> and <str2> may point to the same place.
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
void sh_utol(register char const *str1,register char *str2)
Packit Service a8c26c
/*@
Packit Service a8c26c
	assume str1!=0 && str2!=0
Packit Service a8c26c
	return x satisfying strlen(in str1)==strlen(in str2);
Packit Service a8c26c
@*/ 
Packit Service a8c26c
{
Packit Service a8c26c
	register int c;
Packit Service a8c26c
	for(; c= *((unsigned char*)str1); str1++,str2++)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(isupper(c))
Packit Service a8c26c
			*str2 = tolower(c);
Packit Service a8c26c
		else
Packit Service a8c26c
			*str2 = c;
Packit Service a8c26c
	}
Packit Service a8c26c
	*str2 = 0;
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * format string as a csv field
Packit Service a8c26c
 */
Packit Service a8c26c
static char	*sh_fmtcsv(const char *string)
Packit Service a8c26c
{
Packit Service a8c26c
	register const char *cp = string;
Packit Service a8c26c
	register int c;
Packit Service a8c26c
	int offset;
Packit Service a8c26c
	if(!cp)
Packit Service a8c26c
		return((char*)0);
Packit Service a8c26c
	offset = staktell();
Packit Service a8c26c
	while((c=mbchar(cp)),isaname(c));
Packit Service a8c26c
	if(c==0)
Packit Service a8c26c
		return((char*)string);
Packit Service a8c26c
	stakputc('"');
Packit Service a8c26c
	stakwrite(string,cp-string);
Packit Service a8c26c
	if(c=='"')
Packit Service a8c26c
		stakputc('"');
Packit Service a8c26c
	string = cp;
Packit Service a8c26c
	while(c=mbchar(cp))
Packit Service a8c26c
	{
Packit Service a8c26c
		if(c=='"')
Packit Service a8c26c
		{
Packit Service a8c26c
			stakwrite(string,cp-string);
Packit Service a8c26c
			string = cp;
Packit Service a8c26c
			stakputc('"');
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	if(--cp>string)
Packit Service a8c26c
		stakwrite(string,cp-string);
Packit Service a8c26c
	stakputc('"');
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	return(stakptr(offset));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * print <str> quoting chars so that it can be read by the shell
Packit Service a8c26c
 * puts null terminated result on stack, but doesn't freeze it
Packit Service a8c26c
 */
Packit Service a8c26c
char	*sh_fmtq(const char *string)
Packit Service a8c26c
{
Packit Service a8c26c
	register const char *cp = string, *op;
Packit Service a8c26c
	register int c, state;
Packit Service a8c26c
	int offset;
Packit Service a8c26c
	if(!cp)
Packit Service a8c26c
		return((char*)0);
Packit Service a8c26c
	offset = staktell();
Packit Service a8c26c
	state = ((c= mbchar(cp))==0);
Packit Service a8c26c
	if(isaletter(c))
Packit Service a8c26c
	{
Packit Service a8c26c
		while((c=mbchar(cp)),isaname(c));
Packit Service a8c26c
		if(c==0)
Packit Service a8c26c
			return((char*)string);
Packit Service a8c26c
		if(c=='=')
Packit Service a8c26c
		{
Packit Service a8c26c
			if(*cp==0)
Packit Service a8c26c
				return((char*)string);
Packit Service a8c26c
			if(*cp=='=')
Packit Service a8c26c
				cp++;
Packit Service a8c26c
			c = cp - string;
Packit Service a8c26c
			stakwrite(string,c);
Packit Service a8c26c
			string = cp;
Packit Service a8c26c
			c = mbchar(cp);
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	if(c==0 || c=='#' || c=='~')
Packit Service a8c26c
		state = 1;
Packit Service a8c26c
	for(;c;c= mbchar(cp))
Packit Service a8c26c
	{
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
		if(c=='\'' || c>=128 || c<0 || !iswprint(c)) 
Packit Service a8c26c
#else
Packit Service a8c26c
		if(c=='\'' || !isprint(c))
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
			state = 2;
Packit Service a8c26c
		else if(c==']' || c=='=' || (c!=':' && c<=0x7f && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT))
Packit Service a8c26c
			state |=1;
Packit Service a8c26c
	}
Packit Service a8c26c
	if(state<2)
Packit Service a8c26c
	{
Packit Service a8c26c
		if(state==1)
Packit Service a8c26c
			stakputc('\'');
Packit Service a8c26c
		if(c = --cp - string)
Packit Service a8c26c
			stakwrite(string,c);
Packit Service a8c26c
		if(state==1)
Packit Service a8c26c
			stakputc('\'');
Packit Service a8c26c
	}
Packit Service a8c26c
	else
Packit Service a8c26c
	{
Packit Service a8c26c
		int isbyte=0;
Packit Service a8c26c
		stakwrite("$'",2);
Packit Service a8c26c
		cp = string;
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
		while(op = cp, c= mbchar(cp))
Packit Service a8c26c
#else
Packit Service a8c26c
		while(op = cp, c= *(unsigned char*)cp++)
Packit Service a8c26c
#endif
Packit Service a8c26c
		{
Packit Service a8c26c
			state=1;
Packit Service a8c26c
			switch(c)
Packit Service a8c26c
			{
Packit Service a8c26c
			    case ('a'==97?'\033':39):
Packit Service a8c26c
				c = 'E';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\n':
Packit Service a8c26c
				c = 'n';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\r':
Packit Service a8c26c
				c = 'r';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\t':
Packit Service a8c26c
				c = 't';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\f':
Packit Service a8c26c
				c = 'f';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\b':
Packit Service a8c26c
				c = 'b';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\a':
Packit Service a8c26c
				c = 'a';
Packit Service a8c26c
				break;
Packit Service a8c26c
			    case '\\':	case '\'':
Packit Service a8c26c
				break;
Packit Service a8c26c
			    default:
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
				isbyte = 0;
Packit Service a8c26c
				if(c<0)
Packit Service a8c26c
				{
Packit Service a8c26c
					c = *((unsigned char *)op);
Packit Service a8c26c
					cp = op+1;
Packit Service a8c26c
					isbyte = 1;
Packit Service a8c26c
				}
Packit Service a8c26c
				if(mbwide() && ((cp-op)>1))
Packit Service a8c26c
				{
Packit Service a8c26c
					sfprintf(staksp,"\\u[%x]",c);
Packit Service a8c26c
					continue;
Packit Service a8c26c
				}
Packit Service a8c26c
				else if(!iswprint(c) || isbyte)
Packit Service a8c26c
#else
Packit Service a8c26c
				if(!isprint(c))
Packit Service a8c26c
#endif
Packit Service a8c26c
				{
Packit Service a8c26c
					sfprintf(staksp,"\\x%.2x",c);
Packit Service a8c26c
					continue;
Packit Service a8c26c
				}
Packit Service a8c26c
				state=0;
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if(state)
Packit Service a8c26c
			{
Packit Service a8c26c
				stakputc('\\');
Packit Service a8c26c
				stakputc(c);
Packit Service a8c26c
			}
Packit Service a8c26c
			else
Packit Service a8c26c
				stakwrite(op, cp-op);
Packit Service a8c26c
		}
Packit Service a8c26c
		stakputc('\'');
Packit Service a8c26c
	}
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	return(stakptr(offset));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * print <str> quoting chars so that it can be read by the shell
Packit Service a8c26c
 * puts null terminated result on stack, but doesn't freeze it
Packit Service a8c26c
 * single!=0 limits quoting to '...'
Packit Service a8c26c
 * fold>0 prints raw newlines and inserts appropriately
Packit Service a8c26c
 * escaped newlines every (fold-x) chars
Packit Service a8c26c
 */
Packit Service a8c26c
char	*sh_fmtqf(const char *string, int single, int fold)
Packit Service a8c26c
{
Packit Service a8c26c
	register const char *cp = string;
Packit Service a8c26c
	register const char *bp;
Packit Service a8c26c
	register const char *vp;
Packit Service a8c26c
	register int c;
Packit Service a8c26c
	register int n;
Packit Service a8c26c
	register int q;
Packit Service a8c26c
	register int a;
Packit Service a8c26c
	int offset;
Packit Service a8c26c
Packit Service a8c26c
	if (--fold < 8)
Packit Service a8c26c
		fold = 0;
Packit Service a8c26c
	if(single)
Packit Service a8c26c
		return sh_fmtcsv(cp);
Packit Service a8c26c
	if (!cp || !*cp || !fold || fold && strlen(string) < fold)
Packit Service a8c26c
		return sh_fmtq(cp);
Packit Service a8c26c
	offset = staktell();
Packit Service a8c26c
	single = single ? 1 : 3;
Packit Service a8c26c
	c = mbchar(string);
Packit Service a8c26c
	a = isaletter(c) ? '=' : 0;
Packit Service a8c26c
	vp = cp + 1;
Packit Service a8c26c
	do
Packit Service a8c26c
	{
Packit Service a8c26c
		q = 0;
Packit Service a8c26c
		n = fold;
Packit Service a8c26c
		bp = cp;
Packit Service a8c26c
		while ((!n || n-- > 0) && (c = mbchar(cp)))
Packit Service a8c26c
		{
Packit Service a8c26c
			if (a && !isaname(c))
Packit Service a8c26c
				a = 0;
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
			if (c >= 0x200)
Packit Service a8c26c
				continue;
Packit Service a8c26c
			if (c == '\'' || !iswprint(c))
Packit Service a8c26c
#else
Packit Service a8c26c
			if (c == '\'' || !isprint(c))
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
			{
Packit Service a8c26c
				q = single;
Packit Service a8c26c
				break;
Packit Service a8c26c
			}
Packit Service a8c26c
			if (c == '\n')
Packit Service a8c26c
				q = 1;
Packit Service a8c26c
			else if (c == a)
Packit Service a8c26c
			{
Packit Service a8c26c
				stakwrite(bp, cp - bp);
Packit Service a8c26c
				bp = cp;
Packit Service a8c26c
				vp = cp + 1;
Packit Service a8c26c
				a = 0;
Packit Service a8c26c
			}
Packit Service a8c26c
			else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT)
Packit Service a8c26c
				q = 1;
Packit Service a8c26c
		}
Packit Service a8c26c
		if (q & 2)
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputc('$');
Packit Service a8c26c
			stakputc('\'');
Packit Service a8c26c
			cp = bp;
Packit Service a8c26c
			n = fold - 3;
Packit Service a8c26c
			q = 1;
Packit Service a8c26c
			while (c = mbchar(cp))
Packit Service a8c26c
			{
Packit Service a8c26c
				switch (c)
Packit Service a8c26c
				{
Packit Service a8c26c
		    		case ('a'==97?'\033':39):
Packit Service a8c26c
					c = 'E';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\n':
Packit Service a8c26c
					q = 0;
Packit Service a8c26c
					n = fold - 1;
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\r':
Packit Service a8c26c
					c = 'r';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\t':
Packit Service a8c26c
					c = 't';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\f':
Packit Service a8c26c
					c = 'f';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\b':
Packit Service a8c26c
					c = 'b';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\a':
Packit Service a8c26c
					c = 'a';
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		case '\\':
Packit Service a8c26c
					if (*cp == 'n')
Packit Service a8c26c
					{
Packit Service a8c26c
						c = '\n';
Packit Service a8c26c
						q = 0;
Packit Service a8c26c
						n = fold - 1;
Packit Service a8c26c
						break;
Packit Service a8c26c
					}
Packit Service a8c26c
				case '\'':
Packit Service a8c26c
					break;
Packit Service a8c26c
		    		default:
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
					if(!iswprint(c))
Packit Service a8c26c
#else
Packit Service a8c26c
					if(!isprint(c))
Packit Service a8c26c
#endif
Packit Service a8c26c
					{
Packit Service a8c26c
						if ((n -= 4) <= 0)
Packit Service a8c26c
						{
Packit Service a8c26c
							stakwrite("'\\\n$'", 5);
Packit Service a8c26c
							n = fold - 7;
Packit Service a8c26c
						}
Packit Service a8c26c
						sfprintf(staksp, "\\%03o", c);
Packit Service a8c26c
						continue;
Packit Service a8c26c
					}
Packit Service a8c26c
					q = 0;
Packit Service a8c26c
					break;
Packit Service a8c26c
				}
Packit Service a8c26c
				if ((n -= q + 1) <= 0)
Packit Service a8c26c
				{
Packit Service a8c26c
					if (!q)
Packit Service a8c26c
					{
Packit Service a8c26c
						stakputc('\'');
Packit Service a8c26c
						cp = bp;
Packit Service a8c26c
						break;
Packit Service a8c26c
					}
Packit Service a8c26c
					stakwrite("'\\\n$'", 5);
Packit Service a8c26c
					n = fold - 5;
Packit Service a8c26c
				}
Packit Service a8c26c
				if (q)
Packit Service a8c26c
					stakputc('\\');
Packit Service a8c26c
				else
Packit Service a8c26c
					q = 1;
Packit Service a8c26c
				stakputc(c);
Packit Service a8c26c
				bp = cp;
Packit Service a8c26c
			}
Packit Service a8c26c
			if (!c)
Packit Service a8c26c
				stakputc('\'');
Packit Service a8c26c
		}
Packit Service a8c26c
		else if (q & 1)
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputc('\'');
Packit Service a8c26c
			cp = bp;
Packit Service a8c26c
			n = fold ? (fold - 2) : 0;
Packit Service a8c26c
			while (c = mbchar(cp))
Packit Service a8c26c
			{
Packit Service a8c26c
				if (c == '\n')
Packit Service a8c26c
					n = fold - 1;
Packit Service a8c26c
				else if (n && --n <= 0)
Packit Service a8c26c
				{
Packit Service a8c26c
					n = fold - 2;
Packit Service a8c26c
					stakwrite(bp, --cp - bp);
Packit Service a8c26c
					bp = cp;
Packit Service a8c26c
					stakwrite("'\\\n'", 4);
Packit Service a8c26c
				}
Packit Service a8c26c
				else if (n == 1 && *cp == '\'')
Packit Service a8c26c
				{
Packit Service a8c26c
					n = fold - 5;
Packit Service a8c26c
					stakwrite(bp, --cp - bp);
Packit Service a8c26c
					bp = cp;
Packit Service a8c26c
					stakwrite("'\\\n\\''", 6);
Packit Service a8c26c
				}
Packit Service a8c26c
				else if (c == '\'')
Packit Service a8c26c
				{
Packit Service a8c26c
					stakwrite(bp, cp - bp - 1);
Packit Service a8c26c
					bp = cp;
Packit Service a8c26c
					if (n && (n -= 4) <= 0)
Packit Service a8c26c
					{
Packit Service a8c26c
						n = fold - 5;
Packit Service a8c26c
						stakwrite("'\\\n\\''", 6);
Packit Service a8c26c
					}
Packit Service a8c26c
					else
Packit Service a8c26c
						stakwrite("'\\''", 4);
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			stakwrite(bp, cp - bp - 1);
Packit Service a8c26c
			stakputc('\'');
Packit Service a8c26c
		}
Packit Service a8c26c
		else if (n = fold)
Packit Service a8c26c
		{
Packit Service a8c26c
			cp = bp;
Packit Service a8c26c
			while (c = mbchar(cp))
Packit Service a8c26c
			{
Packit Service a8c26c
				if (--n <= 0)
Packit Service a8c26c
				{
Packit Service a8c26c
					n = fold;
Packit Service a8c26c
					stakwrite(bp, --cp - bp);
Packit Service a8c26c
					bp = cp;
Packit Service a8c26c
					stakwrite("\\\n", 2);
Packit Service a8c26c
				}
Packit Service a8c26c
			}
Packit Service a8c26c
			stakwrite(bp, cp - bp - 1);
Packit Service a8c26c
		}
Packit Service a8c26c
		else
Packit Service a8c26c
			stakwrite(bp, cp - bp);
Packit Service a8c26c
		if (c)
Packit Service a8c26c
		{
Packit Service a8c26c
			stakputc('\\');
Packit Service a8c26c
			stakputc('\n');
Packit Service a8c26c
		}
Packit Service a8c26c
	} while (c);
Packit Service a8c26c
	stakputc(0);
Packit Service a8c26c
	return(stakptr(offset));
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if SHOPT_MULTIBYTE
Packit Service a8c26c
	int sh_strchr(const char *string, register const char *dp)
Packit Service a8c26c
	{
Packit Service a8c26c
		wchar_t c, d;
Packit Service a8c26c
		register const char *cp=string;
Packit Service a8c26c
		mbinit();
Packit Service a8c26c
		d = mbchar(dp); 
Packit Service a8c26c
		mbinit();
Packit Service a8c26c
		while(c = mbchar(cp))
Packit Service a8c26c
		{
Packit Service a8c26c
			if(c==d)
Packit Service a8c26c
				return(cp-string);
Packit Service a8c26c
		}
Packit Service a8c26c
		if(d==0)
Packit Service a8c26c
			return(cp-string);
Packit Service a8c26c
		return(-1);
Packit Service a8c26c
	}
Packit Service a8c26c
#endif /* SHOPT_MULTIBYTE */
Packit Service a8c26c
Packit Service a8c26c
const char *_sh_translate(const char *message)
Packit Service a8c26c
{
Packit Service a8c26c
#if ERROR_VERSION >= 20000317L
Packit Service a8c26c
	return(ERROR_translate(0,0,e_dict,message));
Packit Service a8c26c
#else
Packit Service a8c26c
#if ERROR_VERSION >= 20000101L
Packit Service a8c26c
	return(ERROR_translate(e_dict,message));
Packit Service a8c26c
#else
Packit Service a8c26c
	return(ERROR_translate(message,1));
Packit Service a8c26c
#endif
Packit Service a8c26c
#endif
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/*
Packit Service a8c26c
 * change '['identifier']' to identifier
Packit Service a8c26c
 * character before <str> must be a '['
Packit Service a8c26c
 * returns pointer to last character
Packit Service a8c26c
 */
Packit Service a8c26c
char *sh_checkid(char *str, char *last)
Packit Service a8c26c
{
Packit Service a8c26c
	register unsigned char *cp = (unsigned char*)str;
Packit Service a8c26c
	register unsigned char *v = cp;
Packit Service a8c26c
	register int c;
Packit Service a8c26c
	if(c=mbchar(cp),isaletter(c))
Packit Service a8c26c
		while(c=mbchar(cp),isaname(c));
Packit Service a8c26c
	if(c==']' && (!last || ((char*)cp==last)))
Packit Service a8c26c
	{
Packit Service a8c26c
		/* eliminate [ and ] */
Packit Service a8c26c
		while(v < cp)
Packit Service a8c26c
		{
Packit Service a8c26c
			v[-1] = *v;
Packit Service a8c26c
			v++;
Packit Service a8c26c
		}
Packit Service a8c26c
		if(last)
Packit Service a8c26c
			last -=2;
Packit Service a8c26c
		else
Packit Service a8c26c
		{
Packit Service a8c26c
			while(*v)
Packit Service a8c26c
			{
Packit Service a8c26c
				v[-2] = *v;
Packit Service a8c26c
				v++;
Packit Service a8c26c
			}
Packit Service a8c26c
			v[-2] = 0;
Packit Service a8c26c
			last = (char*)v;
Packit Service a8c26c
		}
Packit Service a8c26c
	}
Packit Service a8c26c
	return(last);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#if	_AST_VERSION  <= 20000317L
Packit Service a8c26c
char *fmtident(const char *string)
Packit Service a8c26c
{
Packit Service a8c26c
	return((char*)string);
Packit Service a8c26c
}
Packit Service a8c26c
#endif