14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * string processing routines for Korn shell
234887Schin *
244887Schin */
254887Schin
264887Schin #include <ast.h>
274887Schin #include <ast_wchar.h>
284887Schin #include "defs.h"
294887Schin #include <stak.h>
304887Schin #include <ccode.h>
314887Schin #include "shtable.h"
324887Schin #include "lexstates.h"
334887Schin #include "national.h"
344887Schin
354887Schin #if !SHOPT_MULTIBYTE
364887Schin #define mbchar(p) (*(unsigned char*)p++)
374887Schin #endif
384887Schin
394887Schin #if _hdr_wctype
404887Schin # include <wctype.h>
414887Schin #endif
424887Schin
434887Schin #if !_lib_iswprint && !defined(iswprint)
444887Schin # define iswprint(c) (((c)&~0377) || isprint(c))
454887Schin #endif
464887Schin
474887Schin
484887Schin /*
494887Schin * Table lookup routine
504887Schin * <table> is searched for string <sp> and corresponding value is returned
514887Schin * This is only used for small tables and is used to save non-sharable memory
524887Schin */
534887Schin
sh_locate(register const char * sp,const Shtable_t * table,int size)544887Schin const Shtable_t *sh_locate(register const char *sp,const Shtable_t *table,int size)
554887Schin {
564887Schin register int first;
574887Schin register const Shtable_t *tp;
584887Schin register int c;
594887Schin static const Shtable_t empty = {0,0};
604887Schin if(sp==0 || (first= *sp)==0)
614887Schin return(&empty);
624887Schin tp=table;
634887Schin while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first))
644887Schin {
654887Schin if(first == c && strcmp(sp,tp->sh_name)==0)
664887Schin return(tp);
674887Schin tp = (Shtable_t*)((char*)tp+size);
684887Schin }
694887Schin return(&empty);
704887Schin }
714887Schin
724887Schin /*
734887Schin * shtab_options lookup routine
744887Schin */
754887Schin
764887Schin #define sep(c) ((c)=='-'||(c)=='_')
774887Schin
sh_lookopt(register const char * sp,int * invert)784887Schin int sh_lookopt(register const char *sp, int *invert)
794887Schin {
804887Schin register int first;
814887Schin register const Shtable_t *tp;
824887Schin register int c;
834887Schin register const char *s, *t, *sw, *tw;
844887Schin int amb;
854887Schin int hit;
864887Schin int inv;
874887Schin int no;
884887Schin if(sp==0)
894887Schin return(0);
904887Schin if(*sp=='n' && *(sp+1)=='o' && (*(sp+2)!='t' || *(sp+3)!='i'))
914887Schin {
924887Schin sp+=2;
934887Schin if(sep(*sp))
944887Schin sp++;
954887Schin *invert = !*invert;
964887Schin }
974887Schin if((first= *sp)==0)
984887Schin return(0);
994887Schin tp=shtab_options;
1004887Schin amb=hit=0;
1014887Schin for(;;)
1024887Schin {
1034887Schin t=tp->sh_name;
1044887Schin if(no = *t=='n' && *(t+1)=='o' && *(t+2)!='t')
1054887Schin t+=2;
1064887Schin if(!(c= *t))
1074887Schin break;
1084887Schin if(first == c)
1094887Schin {
1104887Schin if(strcmp(sp,t)==0)
1114887Schin {
1124887Schin *invert ^= no;
1134887Schin return(tp->sh_number);
1144887Schin }
1154887Schin s=sw=sp;
1164887Schin tw=t;
1174887Schin for(;;)
1184887Schin {
1194887Schin if(!*s || *s=='=')
1204887Schin {
1214887Schin if (*s == '=' && !strtol(s+1, NiL, 0))
1224887Schin no = !no;
1234887Schin if (!*t)
1244887Schin {
1254887Schin *invert ^= no;
1264887Schin return(tp->sh_number);
1274887Schin }
1284887Schin if (hit || amb)
1294887Schin {
1304887Schin hit = 0;
1314887Schin amb = 1;
1324887Schin }
1334887Schin else
1344887Schin {
1354887Schin hit = tp->sh_number;
1364887Schin inv = no;
1374887Schin }
1384887Schin break;
1394887Schin }
1404887Schin else if(!*t)
1414887Schin break;
1424887Schin else if(sep(*s))
1434887Schin sw = ++s;
1444887Schin else if(sep(*t))
1454887Schin tw = ++t;
1464887Schin else if(*s==*t)
1474887Schin {
1484887Schin s++;
1494887Schin t++;
1504887Schin }
1514887Schin else if(s==sw && t==tw)
1524887Schin break;
1534887Schin else
1544887Schin {
1554887Schin if(t!=tw)
1564887Schin {
1574887Schin while(*t && !sep(*t))
1584887Schin t++;
1594887Schin if(!*t)
1604887Schin break;
1614887Schin tw = ++t;
1624887Schin }
1634887Schin while (s>sw && *s!=*t)
1644887Schin s--;
1654887Schin }
1664887Schin }
1674887Schin }
1684887Schin tp = (Shtable_t*)((char*)tp+sizeof(*shtab_options));
1694887Schin }
1704887Schin if(hit)
1714887Schin *invert ^= inv;
1724887Schin return(hit);
1734887Schin }
1744887Schin
1754887Schin /*
1764887Schin * look for the substring <oldsp> in <string> and replace with <newsp>
1774887Schin * The new string is put on top of the stack
1784887Schin */
sh_substitute(const char * string,const char * oldsp,char * newsp)1794887Schin char *sh_substitute(const char *string,const char *oldsp,char *newsp)
1804887Schin /*@
1814887Schin assume string!=NULL && oldsp!=NULL && newsp!=NULL;
1824887Schin return x satisfying x==NULL ||
1834887Schin strlen(x)==(strlen(in string)+strlen(in newsp)-strlen(in oldsp));
1844887Schin @*/
1854887Schin {
1864887Schin register const char *sp = string;
1874887Schin register const char *cp;
1884887Schin const char *savesp = 0;
1894887Schin stakseek(0);
1904887Schin if(*sp==0)
1914887Schin return((char*)0);
1924887Schin if(*(cp=oldsp) == 0)
1934887Schin goto found;
1944887Schin #if SHOPT_MULTIBYTE
1954887Schin mbinit();
1964887Schin #endif /* SHOPT_MULTIBYTE */
1974887Schin do
1984887Schin {
1994887Schin /* skip to first character which matches start of oldsp */
2004887Schin while(*sp && (savesp==sp || *sp != *cp))
2014887Schin {
2024887Schin #if SHOPT_MULTIBYTE
2034887Schin /* skip a whole character at a time */
2044887Schin int c = mbsize(sp);
2054887Schin if(c < 0)
2064887Schin sp++;
2074887Schin while(c-- > 0)
2084887Schin #endif /* SHOPT_MULTIBYTE */
2094887Schin stakputc(*sp++);
2104887Schin }
2114887Schin if(*sp == 0)
2124887Schin return((char*)0);
2134887Schin savesp = sp;
2144887Schin for(;*cp;cp++)
2154887Schin {
2164887Schin if(*cp != *sp++)
2174887Schin break;
2184887Schin }
2194887Schin if(*cp==0)
2204887Schin /* match found */
2214887Schin goto found;
2224887Schin sp = savesp;
2234887Schin cp = oldsp;
2244887Schin }
2254887Schin while(*sp);
2264887Schin return((char*)0);
2274887Schin
2284887Schin found:
2294887Schin /* copy new */
2304887Schin stakputs(newsp);
2314887Schin /* copy rest of string */
2324887Schin stakputs(sp);
2334887Schin return(stakfreeze(1));
2344887Schin }
2354887Schin
2364887Schin /*
2374887Schin * TRIM(sp)
2384887Schin * Remove escape characters from characters in <sp> and eliminate quoted nulls.
2394887Schin */
2404887Schin
sh_trim(register char * sp)2414887Schin void sh_trim(register char *sp)
2424887Schin /*@
2434887Schin assume sp!=NULL;
2444887Schin promise strlen(in sp) <= in strlen(sp);
2454887Schin @*/
2464887Schin {
2474887Schin register char *dp;
2484887Schin register int c;
2494887Schin if(sp)
2504887Schin {
2514887Schin dp = sp;
2524887Schin while(c= *sp)
2534887Schin {
2544887Schin #if SHOPT_MULTIBYTE
2554887Schin int len;
2564887Schin if(mbwide() && (len=mbsize(sp))>1)
2574887Schin {
2588462SApril.Chin@Sun.COM memmove(dp, sp, len);
2594887Schin dp += len;
2604887Schin sp += len;
2614887Schin continue;
2624887Schin }
2634887Schin #endif /* SHOPT_MULTIBYTE */
2644887Schin sp++;
2654887Schin if(c == '\\')
2664887Schin c = *sp++;
2674887Schin if(c)
2684887Schin *dp++ = c;
2694887Schin }
2704887Schin *dp = 0;
2714887Schin }
2724887Schin }
2734887Schin
2744887Schin /*
2754887Schin * copy <str1> to <str2> changing upper case to lower case
2764887Schin * <str2> must be big enough to hold <str1>
2774887Schin * <str1> and <str2> may point to the same place.
2784887Schin */
2794887Schin
sh_utol(register char const * str1,register char * str2)2804887Schin void sh_utol(register char const *str1,register char *str2)
2814887Schin /*@
2824887Schin assume str1!=0 && str2!=0
2834887Schin return x satisfying strlen(in str1)==strlen(in str2);
2844887Schin @*/
2854887Schin {
2864887Schin register int c;
2874887Schin for(; c= *((unsigned char*)str1); str1++,str2++)
2884887Schin {
2894887Schin if(isupper(c))
2904887Schin *str2 = tolower(c);
2914887Schin else
2924887Schin *str2 = c;
2934887Schin }
2944887Schin *str2 = 0;
2954887Schin }
2964887Schin
2974887Schin /*
2984887Schin * print <str> quoting chars so that it can be read by the shell
2994887Schin * puts null terminated result on stack, but doesn't freeze it
3004887Schin */
sh_fmtq(const char * string)3014887Schin char *sh_fmtq(const char *string)
3024887Schin {
3038462SApril.Chin@Sun.COM register const char *cp = string, *op;
3044887Schin register int c, state;
3054887Schin int offset;
3064887Schin if(!cp)
3074887Schin return((char*)0);
3084887Schin offset = staktell();
3094887Schin #if SHOPT_MULTIBYTE
3104887Schin state = ((c= mbchar(cp))==0);
3114887Schin #else
3124887Schin state = ((c= *(unsigned char*)cp++)==0);
3134887Schin #endif
3144887Schin if(isaletter(c))
3154887Schin {
3164887Schin #if SHOPT_MULTIBYTE
3174887Schin while((c=mbchar(cp)),isaname(c));
3184887Schin #else
3194887Schin while((c = *(unsigned char*)cp++),isaname(c));
3204887Schin #endif
3214887Schin if(c==0)
3224887Schin return((char*)string);
3234887Schin if(c=='=')
3244887Schin {
3254887Schin if(*cp==0)
3264887Schin return((char*)string);
3274887Schin c = cp - string;
3284887Schin stakwrite(string,c);
3294887Schin string = cp;
3304887Schin #if SHOPT_MULTIBYTE
3314887Schin c = mbchar(cp);
3324887Schin #else
3334887Schin c = *(unsigned char*)cp++;
3344887Schin #endif
3354887Schin }
3364887Schin }
3374887Schin if(c==0 || c=='#' || c=='~')
3384887Schin state = 1;
3394887Schin #if SHOPT_MULTIBYTE
3404887Schin for(;c;c= mbchar(cp))
3414887Schin #else
3424887Schin for(;c; c= *(unsigned char*)cp++)
3434887Schin #endif
3444887Schin {
3454887Schin #if SHOPT_MULTIBYTE
3464887Schin if(c=='\'' || !iswprint(c))
3474887Schin #else
3484887Schin if(c=='\'' || !isprint(c))
3494887Schin #endif /* SHOPT_MULTIBYTE */
3504887Schin state = 2;
3518462SApril.Chin@Sun.COM else if(c==']' || (c!=':' && c<=0xff && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT))
3524887Schin state |=1;
3534887Schin }
3544887Schin if(state<2)
3554887Schin {
3564887Schin if(state==1)
3574887Schin stakputc('\'');
3584887Schin if(c = --cp - string)
3594887Schin stakwrite(string,c);
3604887Schin if(state==1)
3614887Schin stakputc('\'');
3624887Schin }
3634887Schin else
3644887Schin {
3654887Schin stakwrite("$'",2);
3664887Schin cp = string;
3674887Schin #if SHOPT_MULTIBYTE
3688462SApril.Chin@Sun.COM while(op = cp, c= mbchar(cp))
3694887Schin #else
3708462SApril.Chin@Sun.COM while(op = cp, c= *(unsigned char*)cp++)
3714887Schin #endif
3724887Schin {
3734887Schin state=1;
3744887Schin switch(c)
3754887Schin {
3764887Schin case ('a'==97?'\033':39):
3774887Schin c = 'E';
3784887Schin break;
3794887Schin case '\n':
3804887Schin c = 'n';
3814887Schin break;
3824887Schin case '\r':
3834887Schin c = 'r';
3844887Schin break;
3854887Schin case '\t':
3864887Schin c = 't';
3874887Schin break;
3884887Schin case '\f':
3894887Schin c = 'f';
3904887Schin break;
3914887Schin case '\b':
3924887Schin c = 'b';
3934887Schin break;
3944887Schin case '\a':
3954887Schin c = 'a';
3964887Schin break;
3974887Schin case '\\': case '\'':
3984887Schin break;
3994887Schin default:
4004887Schin #if SHOPT_MULTIBYTE
4014887Schin if(!iswprint(c))
4028462SApril.Chin@Sun.COM {
4038462SApril.Chin@Sun.COM while(op<cp)
4048462SApril.Chin@Sun.COM sfprintf(staksp,"\\%.3o",*(unsigned char*)op++);
4058462SApril.Chin@Sun.COM continue;
4068462SApril.Chin@Sun.COM }
4074887Schin #else
4084887Schin if(!isprint(c))
4094887Schin {
4104887Schin sfprintf(staksp,"\\%.3o",c);
4114887Schin continue;
4124887Schin }
4138462SApril.Chin@Sun.COM #endif
4144887Schin state=0;
4154887Schin break;
4164887Schin }
4174887Schin if(state)
4188462SApril.Chin@Sun.COM {
4194887Schin stakputc('\\');
4208462SApril.Chin@Sun.COM stakputc(c);
4218462SApril.Chin@Sun.COM }
4228462SApril.Chin@Sun.COM else
4238462SApril.Chin@Sun.COM stakwrite(op, cp-op);
4244887Schin }
4254887Schin stakputc('\'');
4264887Schin }
4274887Schin stakputc(0);
4284887Schin return(stakptr(offset));
4294887Schin }
4304887Schin
4314887Schin /*
4324887Schin * print <str> quoting chars so that it can be read by the shell
4334887Schin * puts null terminated result on stack, but doesn't freeze it
4344887Schin * single!=0 limits quoting to '...'
4354887Schin * fold>0 prints raw newlines and inserts appropriately
4364887Schin * escaped newlines every (fold-x) chars
4374887Schin */
sh_fmtqf(const char * string,int single,int fold)4384887Schin char *sh_fmtqf(const char *string, int single, int fold)
4394887Schin {
4404887Schin register const char *cp = string;
4414887Schin register const char *bp;
4424887Schin register const char *vp;
4434887Schin register int c;
4444887Schin register int n;
4454887Schin register int q;
4464887Schin register int a;
4474887Schin int offset;
4484887Schin
4494887Schin if (--fold < 8)
4504887Schin fold = 0;
4514887Schin if (!cp || !*cp || !single && !fold || fold && strlen(string) < fold)
4524887Schin return sh_fmtq(cp);
4534887Schin offset = staktell();
4544887Schin single = single ? 1 : 3;
4554887Schin c = mbchar(string);
4564887Schin a = isaletter(c) ? '=' : 0;
4574887Schin vp = cp + 1;
4584887Schin do
4594887Schin {
4604887Schin q = 0;
4614887Schin n = fold;
4624887Schin bp = cp;
4634887Schin while ((!n || n-- > 0) && (c = mbchar(cp)))
4644887Schin {
4654887Schin if (a && !isaname(c))
4664887Schin a = 0;
4674887Schin #if SHOPT_MULTIBYTE
4684887Schin if (c >= 0x200)
4694887Schin continue;
4704887Schin if (c == '\'' || !iswprint(c))
4714887Schin #else
4724887Schin if (c == '\'' || !isprint(c))
4734887Schin #endif /* SHOPT_MULTIBYTE */
4744887Schin {
4754887Schin q = single;
4764887Schin break;
4774887Schin }
4784887Schin if (c == '\n')
4794887Schin q = 1;
4804887Schin else if (c == a)
4814887Schin {
4824887Schin stakwrite(bp, cp - bp);
4834887Schin bp = cp;
4844887Schin vp = cp + 1;
4854887Schin a = 0;
4864887Schin }
4874887Schin else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT)
4884887Schin q = 1;
4894887Schin }
4904887Schin if (q & 2)
4914887Schin {
4924887Schin stakputc('$');
4934887Schin stakputc('\'');
4944887Schin cp = bp;
4954887Schin n = fold - 3;
4964887Schin q = 1;
4974887Schin while (c = mbchar(cp))
4984887Schin {
4994887Schin switch (c)
5004887Schin {
5014887Schin case ('a'==97?'\033':39):
5024887Schin c = 'E';
5034887Schin break;
5044887Schin case '\n':
5054887Schin q = 0;
5064887Schin n = fold - 1;
5074887Schin break;
5084887Schin case '\r':
5094887Schin c = 'r';
5104887Schin break;
5114887Schin case '\t':
5124887Schin c = 't';
5134887Schin break;
5144887Schin case '\f':
5154887Schin c = 'f';
5164887Schin break;
5174887Schin case '\b':
5184887Schin c = 'b';
5194887Schin break;
5204887Schin case '\a':
5214887Schin c = 'a';
5224887Schin break;
5234887Schin case '\\':
5244887Schin if (*cp == 'n')
5254887Schin {
5264887Schin c = '\n';
5274887Schin q = 0;
5284887Schin n = fold - 1;
5294887Schin break;
5304887Schin }
5314887Schin case '\'':
5324887Schin break;
5334887Schin default:
5344887Schin #if SHOPT_MULTIBYTE
5354887Schin if(!iswprint(c))
5364887Schin #else
5374887Schin if(!isprint(c))
5384887Schin #endif
5394887Schin {
5404887Schin if ((n -= 4) <= 0)
5414887Schin {
5424887Schin stakwrite("'\\\n$'", 5);
5434887Schin n = fold - 7;
5444887Schin }
5454887Schin sfprintf(staksp, "\\%03o", c);
5464887Schin continue;
5474887Schin }
5484887Schin q = 0;
5494887Schin break;
5504887Schin }
5514887Schin if ((n -= q + 1) <= 0)
5524887Schin {
5534887Schin if (!q)
5544887Schin {
5554887Schin stakputc('\'');
5564887Schin cp = bp;
5574887Schin break;
5584887Schin }
5594887Schin stakwrite("'\\\n$'", 5);
5604887Schin n = fold - 5;
5614887Schin }
5624887Schin if (q)
5634887Schin stakputc('\\');
5644887Schin else
5654887Schin q = 1;
5664887Schin stakputc(c);
5674887Schin bp = cp;
5684887Schin }
5694887Schin if (!c)
5704887Schin stakputc('\'');
5714887Schin }
5724887Schin else if (q & 1)
5734887Schin {
5744887Schin stakputc('\'');
5754887Schin cp = bp;
5764887Schin n = fold ? (fold - 2) : 0;
5774887Schin while (c = mbchar(cp))
5784887Schin {
5794887Schin if (c == '\n')
5804887Schin n = fold - 1;
5814887Schin else if (n && --n <= 0)
5824887Schin {
5834887Schin n = fold - 2;
5844887Schin stakwrite(bp, --cp - bp);
5854887Schin bp = cp;
5864887Schin stakwrite("'\\\n'", 4);
5874887Schin }
5884887Schin else if (n == 1 && *cp == '\'')
5894887Schin {
5904887Schin n = fold - 5;
5914887Schin stakwrite(bp, --cp - bp);
5924887Schin bp = cp;
5934887Schin stakwrite("'\\\n\\''", 6);
5944887Schin }
5954887Schin else if (c == '\'')
5964887Schin {
5974887Schin stakwrite(bp, cp - bp - 1);
5984887Schin bp = cp;
5994887Schin if (n && (n -= 4) <= 0)
6004887Schin {
6014887Schin n = fold - 5;
6024887Schin stakwrite("'\\\n\\''", 6);
6034887Schin }
6044887Schin else
6054887Schin stakwrite("'\\''", 4);
6064887Schin }
6074887Schin }
6084887Schin stakwrite(bp, cp - bp - 1);
6094887Schin stakputc('\'');
6104887Schin }
6114887Schin else if (n = fold)
6124887Schin {
6134887Schin cp = bp;
6144887Schin while (c = mbchar(cp))
6154887Schin {
6164887Schin if (--n <= 0)
6174887Schin {
6184887Schin n = fold;
6194887Schin stakwrite(bp, --cp - bp);
6204887Schin bp = cp;
6214887Schin stakwrite("\\\n", 2);
6224887Schin }
6234887Schin }
6244887Schin stakwrite(bp, cp - bp - 1);
6254887Schin }
6264887Schin else
6274887Schin stakwrite(bp, cp - bp);
6284887Schin if (c)
6294887Schin {
6304887Schin stakputc('\\');
6314887Schin stakputc('\n');
6324887Schin }
6334887Schin } while (c);
6344887Schin stakputc(0);
6354887Schin return(stakptr(offset));
6364887Schin }
6374887Schin
6384887Schin #if SHOPT_MULTIBYTE
sh_strchr(const char * string,register const char * dp)6394887Schin int sh_strchr(const char *string, register const char *dp)
6404887Schin {
6414887Schin wchar_t c, d;
6424887Schin register const char *cp=string;
6434887Schin mbinit();
6444887Schin d = mbchar(dp);
6454887Schin mbinit();
6464887Schin while(c = mbchar(cp))
6474887Schin {
6484887Schin if(c==d)
6494887Schin return(cp-string);
6504887Schin }
6514887Schin if(d==0)
6524887Schin return(cp-string);
6534887Schin return(-1);
6544887Schin }
6554887Schin #endif /* SHOPT_MULTIBYTE */
6564887Schin
_sh_translate(const char * message)6574887Schin const char *_sh_translate(const char *message)
6584887Schin {
6594887Schin #if ERROR_VERSION >= 20000317L
6604887Schin return(ERROR_translate(0,0,e_dict,message));
6614887Schin #else
6624887Schin #if ERROR_VERSION >= 20000101L
6634887Schin return(ERROR_translate(e_dict,message));
6644887Schin #else
6654887Schin return(ERROR_translate(message,1));
6664887Schin #endif
6674887Schin #endif
6684887Schin }
6694887Schin
6704887Schin /*
6714887Schin * change '['identifier']' to identifier
6724887Schin * character before <str> must be a '['
6734887Schin * returns pointer to last character
6744887Schin */
sh_checkid(char * str,char * last)6754887Schin char *sh_checkid(char *str, char *last)
6764887Schin {
6774887Schin register unsigned char *cp = (unsigned char*)str;
6784887Schin register unsigned char *v = cp;
6794887Schin register int c;
6804887Schin if(c= *cp++,isaletter(c))
6814887Schin while(c= *cp++,isaname(c));
6824887Schin if(c==']' && (!last || ((char*)cp==last)))
6834887Schin {
6844887Schin /* eliminate [ and ] */
6854887Schin while(v < cp)
6864887Schin {
6874887Schin v[-1] = *v;
6884887Schin v++;
6894887Schin }
6904887Schin if(last)
6914887Schin last -=2;
6924887Schin else
6934887Schin {
6944887Schin while(*v)
6954887Schin {
6964887Schin v[-2] = *v;
6974887Schin v++;
6984887Schin }
6994887Schin v[-2] = 0;
7004887Schin last = (char*)v;
7014887Schin }
7024887Schin }
7034887Schin return(last);
7044887Schin }
7054887Schin
7064887Schin #if _AST_VERSION <= 20000317L
fmtident(const char * string)7074887Schin char *fmtident(const char *string)
7084887Schin {
7094887Schin return((char*)string);
7104887Schin }
7114887Schin #endif
712