1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * string processing routines for Korn shell 23*4887Schin * 24*4887Schin */ 25*4887Schin 26*4887Schin #include <ast.h> 27*4887Schin #include <ast_wchar.h> 28*4887Schin #include "defs.h" 29*4887Schin #include <stak.h> 30*4887Schin #include <ctype.h> 31*4887Schin #include <ccode.h> 32*4887Schin #include "shtable.h" 33*4887Schin #include "lexstates.h" 34*4887Schin #include "national.h" 35*4887Schin 36*4887Schin #if !SHOPT_MULTIBYTE 37*4887Schin #define mbchar(p) (*(unsigned char*)p++) 38*4887Schin #endif 39*4887Schin 40*4887Schin #if _hdr_wctype 41*4887Schin # include <wctype.h> 42*4887Schin #endif 43*4887Schin 44*4887Schin #if !_lib_iswprint && !defined(iswprint) 45*4887Schin # define iswprint(c) (((c)&~0377) || isprint(c)) 46*4887Schin #endif 47*4887Schin 48*4887Schin 49*4887Schin /* 50*4887Schin * Table lookup routine 51*4887Schin * <table> is searched for string <sp> and corresponding value is returned 52*4887Schin * This is only used for small tables and is used to save non-sharable memory 53*4887Schin */ 54*4887Schin 55*4887Schin const Shtable_t *sh_locate(register const char *sp,const Shtable_t *table,int size) 56*4887Schin { 57*4887Schin register int first; 58*4887Schin register const Shtable_t *tp; 59*4887Schin register int c; 60*4887Schin static const Shtable_t empty = {0,0}; 61*4887Schin if(sp==0 || (first= *sp)==0) 62*4887Schin return(&empty); 63*4887Schin tp=table; 64*4887Schin while((c= *tp->sh_name) && (CC_NATIVE!=CC_ASCII || c <= first)) 65*4887Schin { 66*4887Schin if(first == c && strcmp(sp,tp->sh_name)==0) 67*4887Schin return(tp); 68*4887Schin tp = (Shtable_t*)((char*)tp+size); 69*4887Schin } 70*4887Schin return(&empty); 71*4887Schin } 72*4887Schin 73*4887Schin /* 74*4887Schin * shtab_options lookup routine 75*4887Schin */ 76*4887Schin 77*4887Schin #define sep(c) ((c)=='-'||(c)=='_') 78*4887Schin 79*4887Schin int sh_lookopt(register const char *sp, int *invert) 80*4887Schin { 81*4887Schin register int first; 82*4887Schin register const Shtable_t *tp; 83*4887Schin register int c; 84*4887Schin register const char *s, *t, *sw, *tw; 85*4887Schin int amb; 86*4887Schin int hit; 87*4887Schin int inv; 88*4887Schin int no; 89*4887Schin if(sp==0) 90*4887Schin return(0); 91*4887Schin if(*sp=='n' && *(sp+1)=='o' && (*(sp+2)!='t' || *(sp+3)!='i')) 92*4887Schin { 93*4887Schin sp+=2; 94*4887Schin if(sep(*sp)) 95*4887Schin sp++; 96*4887Schin *invert = !*invert; 97*4887Schin } 98*4887Schin if((first= *sp)==0) 99*4887Schin return(0); 100*4887Schin tp=shtab_options; 101*4887Schin amb=hit=0; 102*4887Schin for(;;) 103*4887Schin { 104*4887Schin t=tp->sh_name; 105*4887Schin if(no = *t=='n' && *(t+1)=='o' && *(t+2)!='t') 106*4887Schin t+=2; 107*4887Schin if(!(c= *t)) 108*4887Schin break; 109*4887Schin if(first == c) 110*4887Schin { 111*4887Schin if(strcmp(sp,t)==0) 112*4887Schin { 113*4887Schin *invert ^= no; 114*4887Schin return(tp->sh_number); 115*4887Schin } 116*4887Schin s=sw=sp; 117*4887Schin tw=t; 118*4887Schin for(;;) 119*4887Schin { 120*4887Schin if(!*s || *s=='=') 121*4887Schin { 122*4887Schin if (*s == '=' && !strtol(s+1, NiL, 0)) 123*4887Schin no = !no; 124*4887Schin if (!*t) 125*4887Schin { 126*4887Schin *invert ^= no; 127*4887Schin return(tp->sh_number); 128*4887Schin } 129*4887Schin if (hit || amb) 130*4887Schin { 131*4887Schin hit = 0; 132*4887Schin amb = 1; 133*4887Schin } 134*4887Schin else 135*4887Schin { 136*4887Schin hit = tp->sh_number; 137*4887Schin inv = no; 138*4887Schin } 139*4887Schin break; 140*4887Schin } 141*4887Schin else if(!*t) 142*4887Schin break; 143*4887Schin else if(sep(*s)) 144*4887Schin sw = ++s; 145*4887Schin else if(sep(*t)) 146*4887Schin tw = ++t; 147*4887Schin else if(*s==*t) 148*4887Schin { 149*4887Schin s++; 150*4887Schin t++; 151*4887Schin } 152*4887Schin else if(s==sw && t==tw) 153*4887Schin break; 154*4887Schin else 155*4887Schin { 156*4887Schin if(t!=tw) 157*4887Schin { 158*4887Schin while(*t && !sep(*t)) 159*4887Schin t++; 160*4887Schin if(!*t) 161*4887Schin break; 162*4887Schin tw = ++t; 163*4887Schin } 164*4887Schin while (s>sw && *s!=*t) 165*4887Schin s--; 166*4887Schin } 167*4887Schin } 168*4887Schin } 169*4887Schin tp = (Shtable_t*)((char*)tp+sizeof(*shtab_options)); 170*4887Schin } 171*4887Schin if(hit) 172*4887Schin *invert ^= inv; 173*4887Schin return(hit); 174*4887Schin } 175*4887Schin 176*4887Schin /* 177*4887Schin * look for the substring <oldsp> in <string> and replace with <newsp> 178*4887Schin * The new string is put on top of the stack 179*4887Schin */ 180*4887Schin char *sh_substitute(const char *string,const char *oldsp,char *newsp) 181*4887Schin /*@ 182*4887Schin assume string!=NULL && oldsp!=NULL && newsp!=NULL; 183*4887Schin return x satisfying x==NULL || 184*4887Schin strlen(x)==(strlen(in string)+strlen(in newsp)-strlen(in oldsp)); 185*4887Schin @*/ 186*4887Schin { 187*4887Schin register const char *sp = string; 188*4887Schin register const char *cp; 189*4887Schin const char *savesp = 0; 190*4887Schin stakseek(0); 191*4887Schin if(*sp==0) 192*4887Schin return((char*)0); 193*4887Schin if(*(cp=oldsp) == 0) 194*4887Schin goto found; 195*4887Schin #if SHOPT_MULTIBYTE 196*4887Schin mbinit(); 197*4887Schin #endif /* SHOPT_MULTIBYTE */ 198*4887Schin do 199*4887Schin { 200*4887Schin /* skip to first character which matches start of oldsp */ 201*4887Schin while(*sp && (savesp==sp || *sp != *cp)) 202*4887Schin { 203*4887Schin #if SHOPT_MULTIBYTE 204*4887Schin /* skip a whole character at a time */ 205*4887Schin int c = mbsize(sp); 206*4887Schin if(c < 0) 207*4887Schin sp++; 208*4887Schin while(c-- > 0) 209*4887Schin #endif /* SHOPT_MULTIBYTE */ 210*4887Schin stakputc(*sp++); 211*4887Schin } 212*4887Schin if(*sp == 0) 213*4887Schin return((char*)0); 214*4887Schin savesp = sp; 215*4887Schin for(;*cp;cp++) 216*4887Schin { 217*4887Schin if(*cp != *sp++) 218*4887Schin break; 219*4887Schin } 220*4887Schin if(*cp==0) 221*4887Schin /* match found */ 222*4887Schin goto found; 223*4887Schin sp = savesp; 224*4887Schin cp = oldsp; 225*4887Schin } 226*4887Schin while(*sp); 227*4887Schin return((char*)0); 228*4887Schin 229*4887Schin found: 230*4887Schin /* copy new */ 231*4887Schin stakputs(newsp); 232*4887Schin /* copy rest of string */ 233*4887Schin stakputs(sp); 234*4887Schin return(stakfreeze(1)); 235*4887Schin } 236*4887Schin 237*4887Schin /* 238*4887Schin * TRIM(sp) 239*4887Schin * Remove escape characters from characters in <sp> and eliminate quoted nulls. 240*4887Schin */ 241*4887Schin 242*4887Schin void sh_trim(register char *sp) 243*4887Schin /*@ 244*4887Schin assume sp!=NULL; 245*4887Schin promise strlen(in sp) <= in strlen(sp); 246*4887Schin @*/ 247*4887Schin { 248*4887Schin register char *dp; 249*4887Schin register int c; 250*4887Schin if(sp) 251*4887Schin { 252*4887Schin dp = sp; 253*4887Schin while(c= *sp) 254*4887Schin { 255*4887Schin #if SHOPT_MULTIBYTE 256*4887Schin int len; 257*4887Schin if(mbwide() && (len=mbsize(sp))>1) 258*4887Schin { 259*4887Schin dp += len; 260*4887Schin sp += len; 261*4887Schin continue; 262*4887Schin } 263*4887Schin #endif /* SHOPT_MULTIBYTE */ 264*4887Schin sp++; 265*4887Schin if(c == '\\') 266*4887Schin c = *sp++; 267*4887Schin if(c) 268*4887Schin *dp++ = c; 269*4887Schin } 270*4887Schin *dp = 0; 271*4887Schin } 272*4887Schin } 273*4887Schin 274*4887Schin /* 275*4887Schin * copy <str1> to <str2> changing upper case to lower case 276*4887Schin * <str2> must be big enough to hold <str1> 277*4887Schin * <str1> and <str2> may point to the same place. 278*4887Schin */ 279*4887Schin 280*4887Schin void sh_utol(register char const *str1,register char *str2) 281*4887Schin /*@ 282*4887Schin assume str1!=0 && str2!=0 283*4887Schin return x satisfying strlen(in str1)==strlen(in str2); 284*4887Schin @*/ 285*4887Schin { 286*4887Schin register int c; 287*4887Schin for(; c= *((unsigned char*)str1); str1++,str2++) 288*4887Schin { 289*4887Schin if(isupper(c)) 290*4887Schin *str2 = tolower(c); 291*4887Schin else 292*4887Schin *str2 = c; 293*4887Schin } 294*4887Schin *str2 = 0; 295*4887Schin } 296*4887Schin 297*4887Schin /* 298*4887Schin * print <str> quoting chars so that it can be read by the shell 299*4887Schin * puts null terminated result on stack, but doesn't freeze it 300*4887Schin */ 301*4887Schin char *sh_fmtq(const char *string) 302*4887Schin { 303*4887Schin register const char *cp = string; 304*4887Schin register int c, state; 305*4887Schin int offset; 306*4887Schin if(!cp) 307*4887Schin return((char*)0); 308*4887Schin offset = staktell(); 309*4887Schin #if SHOPT_MULTIBYTE 310*4887Schin state = ((c= mbchar(cp))==0); 311*4887Schin #else 312*4887Schin state = ((c= *(unsigned char*)cp++)==0); 313*4887Schin #endif 314*4887Schin if(isaletter(c)) 315*4887Schin { 316*4887Schin #if SHOPT_MULTIBYTE 317*4887Schin while((c=mbchar(cp)),isaname(c)); 318*4887Schin #else 319*4887Schin while((c = *(unsigned char*)cp++),isaname(c)); 320*4887Schin #endif 321*4887Schin if(c==0) 322*4887Schin return((char*)string); 323*4887Schin if(c=='=') 324*4887Schin { 325*4887Schin if(*cp==0) 326*4887Schin return((char*)string); 327*4887Schin c = cp - string; 328*4887Schin stakwrite(string,c); 329*4887Schin string = cp; 330*4887Schin #if SHOPT_MULTIBYTE 331*4887Schin c = mbchar(cp); 332*4887Schin #else 333*4887Schin c = *(unsigned char*)cp++; 334*4887Schin #endif 335*4887Schin } 336*4887Schin } 337*4887Schin if(c==0 || c=='#' || c=='~') 338*4887Schin state = 1; 339*4887Schin #if SHOPT_MULTIBYTE 340*4887Schin for(;c;c= mbchar(cp)) 341*4887Schin #else 342*4887Schin for(;c; c= *(unsigned char*)cp++) 343*4887Schin #endif 344*4887Schin { 345*4887Schin #if SHOPT_MULTIBYTE 346*4887Schin if(c>=0x200) 347*4887Schin continue; 348*4887Schin if(c=='\'' || !iswprint(c)) 349*4887Schin #else 350*4887Schin if(c=='\'' || !isprint(c)) 351*4887Schin #endif /* SHOPT_MULTIBYTE */ 352*4887Schin state = 2; 353*4887Schin else if(c==']' || (c!=':' && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT)) 354*4887Schin state |=1; 355*4887Schin } 356*4887Schin if(state<2) 357*4887Schin { 358*4887Schin if(state==1) 359*4887Schin stakputc('\''); 360*4887Schin if(c = --cp - string) 361*4887Schin stakwrite(string,c); 362*4887Schin if(state==1) 363*4887Schin stakputc('\''); 364*4887Schin } 365*4887Schin else 366*4887Schin { 367*4887Schin stakwrite("$'",2); 368*4887Schin cp = string; 369*4887Schin #if SHOPT_MULTIBYTE 370*4887Schin while(c= mbchar(cp)) 371*4887Schin #else 372*4887Schin while(c= *(unsigned char*)cp++) 373*4887Schin #endif 374*4887Schin { 375*4887Schin state=1; 376*4887Schin switch(c) 377*4887Schin { 378*4887Schin case ('a'==97?'\033':39): 379*4887Schin c = 'E'; 380*4887Schin break; 381*4887Schin case '\n': 382*4887Schin c = 'n'; 383*4887Schin break; 384*4887Schin case '\r': 385*4887Schin c = 'r'; 386*4887Schin break; 387*4887Schin case '\t': 388*4887Schin c = 't'; 389*4887Schin break; 390*4887Schin case '\f': 391*4887Schin c = 'f'; 392*4887Schin break; 393*4887Schin case '\b': 394*4887Schin c = 'b'; 395*4887Schin break; 396*4887Schin case '\a': 397*4887Schin c = 'a'; 398*4887Schin break; 399*4887Schin case '\\': case '\'': 400*4887Schin break; 401*4887Schin default: 402*4887Schin #if SHOPT_MULTIBYTE 403*4887Schin if(!iswprint(c)) 404*4887Schin #else 405*4887Schin if(!isprint(c)) 406*4887Schin #endif 407*4887Schin { 408*4887Schin sfprintf(staksp,"\\%.3o",c); 409*4887Schin continue; 410*4887Schin } 411*4887Schin state=0; 412*4887Schin break; 413*4887Schin } 414*4887Schin if(state) 415*4887Schin stakputc('\\'); 416*4887Schin stakputc(c); 417*4887Schin } 418*4887Schin stakputc('\''); 419*4887Schin } 420*4887Schin stakputc(0); 421*4887Schin return(stakptr(offset)); 422*4887Schin } 423*4887Schin 424*4887Schin /* 425*4887Schin * print <str> quoting chars so that it can be read by the shell 426*4887Schin * puts null terminated result on stack, but doesn't freeze it 427*4887Schin * single!=0 limits quoting to '...' 428*4887Schin * fold>0 prints raw newlines and inserts appropriately 429*4887Schin * escaped newlines every (fold-x) chars 430*4887Schin */ 431*4887Schin char *sh_fmtqf(const char *string, int single, int fold) 432*4887Schin { 433*4887Schin register const char *cp = string; 434*4887Schin register const char *bp; 435*4887Schin register const char *vp; 436*4887Schin register int c; 437*4887Schin register int n; 438*4887Schin register int q; 439*4887Schin register int a; 440*4887Schin int offset; 441*4887Schin 442*4887Schin if (--fold < 8) 443*4887Schin fold = 0; 444*4887Schin if (!cp || !*cp || !single && !fold || fold && strlen(string) < fold) 445*4887Schin return sh_fmtq(cp); 446*4887Schin offset = staktell(); 447*4887Schin single = single ? 1 : 3; 448*4887Schin c = mbchar(string); 449*4887Schin a = isaletter(c) ? '=' : 0; 450*4887Schin vp = cp + 1; 451*4887Schin do 452*4887Schin { 453*4887Schin q = 0; 454*4887Schin n = fold; 455*4887Schin bp = cp; 456*4887Schin while ((!n || n-- > 0) && (c = mbchar(cp))) 457*4887Schin { 458*4887Schin if (a && !isaname(c)) 459*4887Schin a = 0; 460*4887Schin #if SHOPT_MULTIBYTE 461*4887Schin if (c >= 0x200) 462*4887Schin continue; 463*4887Schin if (c == '\'' || !iswprint(c)) 464*4887Schin #else 465*4887Schin if (c == '\'' || !isprint(c)) 466*4887Schin #endif /* SHOPT_MULTIBYTE */ 467*4887Schin { 468*4887Schin q = single; 469*4887Schin break; 470*4887Schin } 471*4887Schin if (c == '\n') 472*4887Schin q = 1; 473*4887Schin else if (c == a) 474*4887Schin { 475*4887Schin stakwrite(bp, cp - bp); 476*4887Schin bp = cp; 477*4887Schin vp = cp + 1; 478*4887Schin a = 0; 479*4887Schin } 480*4887Schin else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT) 481*4887Schin q = 1; 482*4887Schin } 483*4887Schin if (q & 2) 484*4887Schin { 485*4887Schin stakputc('$'); 486*4887Schin stakputc('\''); 487*4887Schin cp = bp; 488*4887Schin n = fold - 3; 489*4887Schin q = 1; 490*4887Schin while (c = mbchar(cp)) 491*4887Schin { 492*4887Schin switch (c) 493*4887Schin { 494*4887Schin case ('a'==97?'\033':39): 495*4887Schin c = 'E'; 496*4887Schin break; 497*4887Schin case '\n': 498*4887Schin q = 0; 499*4887Schin n = fold - 1; 500*4887Schin break; 501*4887Schin case '\r': 502*4887Schin c = 'r'; 503*4887Schin break; 504*4887Schin case '\t': 505*4887Schin c = 't'; 506*4887Schin break; 507*4887Schin case '\f': 508*4887Schin c = 'f'; 509*4887Schin break; 510*4887Schin case '\b': 511*4887Schin c = 'b'; 512*4887Schin break; 513*4887Schin case '\a': 514*4887Schin c = 'a'; 515*4887Schin break; 516*4887Schin case '\\': 517*4887Schin if (*cp == 'n') 518*4887Schin { 519*4887Schin c = '\n'; 520*4887Schin q = 0; 521*4887Schin n = fold - 1; 522*4887Schin break; 523*4887Schin } 524*4887Schin case '\'': 525*4887Schin break; 526*4887Schin default: 527*4887Schin #if SHOPT_MULTIBYTE 528*4887Schin if(!iswprint(c)) 529*4887Schin #else 530*4887Schin if(!isprint(c)) 531*4887Schin #endif 532*4887Schin { 533*4887Schin if ((n -= 4) <= 0) 534*4887Schin { 535*4887Schin stakwrite("'\\\n$'", 5); 536*4887Schin n = fold - 7; 537*4887Schin } 538*4887Schin sfprintf(staksp, "\\%03o", c); 539*4887Schin continue; 540*4887Schin } 541*4887Schin q = 0; 542*4887Schin break; 543*4887Schin } 544*4887Schin if ((n -= q + 1) <= 0) 545*4887Schin { 546*4887Schin if (!q) 547*4887Schin { 548*4887Schin stakputc('\''); 549*4887Schin cp = bp; 550*4887Schin break; 551*4887Schin } 552*4887Schin stakwrite("'\\\n$'", 5); 553*4887Schin n = fold - 5; 554*4887Schin } 555*4887Schin if (q) 556*4887Schin stakputc('\\'); 557*4887Schin else 558*4887Schin q = 1; 559*4887Schin stakputc(c); 560*4887Schin bp = cp; 561*4887Schin } 562*4887Schin if (!c) 563*4887Schin stakputc('\''); 564*4887Schin } 565*4887Schin else if (q & 1) 566*4887Schin { 567*4887Schin stakputc('\''); 568*4887Schin cp = bp; 569*4887Schin n = fold ? (fold - 2) : 0; 570*4887Schin while (c = mbchar(cp)) 571*4887Schin { 572*4887Schin if (c == '\n') 573*4887Schin n = fold - 1; 574*4887Schin else if (n && --n <= 0) 575*4887Schin { 576*4887Schin n = fold - 2; 577*4887Schin stakwrite(bp, --cp - bp); 578*4887Schin bp = cp; 579*4887Schin stakwrite("'\\\n'", 4); 580*4887Schin } 581*4887Schin else if (n == 1 && *cp == '\'') 582*4887Schin { 583*4887Schin n = fold - 5; 584*4887Schin stakwrite(bp, --cp - bp); 585*4887Schin bp = cp; 586*4887Schin stakwrite("'\\\n\\''", 6); 587*4887Schin } 588*4887Schin else if (c == '\'') 589*4887Schin { 590*4887Schin stakwrite(bp, cp - bp - 1); 591*4887Schin bp = cp; 592*4887Schin if (n && (n -= 4) <= 0) 593*4887Schin { 594*4887Schin n = fold - 5; 595*4887Schin stakwrite("'\\\n\\''", 6); 596*4887Schin } 597*4887Schin else 598*4887Schin stakwrite("'\\''", 4); 599*4887Schin } 600*4887Schin } 601*4887Schin stakwrite(bp, cp - bp - 1); 602*4887Schin stakputc('\''); 603*4887Schin } 604*4887Schin else if (n = fold) 605*4887Schin { 606*4887Schin cp = bp; 607*4887Schin while (c = mbchar(cp)) 608*4887Schin { 609*4887Schin if (--n <= 0) 610*4887Schin { 611*4887Schin n = fold; 612*4887Schin stakwrite(bp, --cp - bp); 613*4887Schin bp = cp; 614*4887Schin stakwrite("\\\n", 2); 615*4887Schin } 616*4887Schin } 617*4887Schin stakwrite(bp, cp - bp - 1); 618*4887Schin } 619*4887Schin else 620*4887Schin stakwrite(bp, cp - bp); 621*4887Schin if (c) 622*4887Schin { 623*4887Schin stakputc('\\'); 624*4887Schin stakputc('\n'); 625*4887Schin } 626*4887Schin } while (c); 627*4887Schin stakputc(0); 628*4887Schin return(stakptr(offset)); 629*4887Schin } 630*4887Schin 631*4887Schin #if SHOPT_MULTIBYTE 632*4887Schin int sh_strchr(const char *string, register const char *dp) 633*4887Schin { 634*4887Schin wchar_t c, d; 635*4887Schin register const char *cp=string; 636*4887Schin mbinit(); 637*4887Schin d = mbchar(dp); 638*4887Schin mbinit(); 639*4887Schin while(c = mbchar(cp)) 640*4887Schin { 641*4887Schin if(c==d) 642*4887Schin return(cp-string); 643*4887Schin } 644*4887Schin if(d==0) 645*4887Schin return(cp-string); 646*4887Schin return(-1); 647*4887Schin } 648*4887Schin #endif /* SHOPT_MULTIBYTE */ 649*4887Schin 650*4887Schin const char *_sh_translate(const char *message) 651*4887Schin { 652*4887Schin #if ERROR_VERSION >= 20000317L 653*4887Schin return(ERROR_translate(0,0,e_dict,message)); 654*4887Schin #else 655*4887Schin #if ERROR_VERSION >= 20000101L 656*4887Schin return(ERROR_translate(e_dict,message)); 657*4887Schin #else 658*4887Schin return(ERROR_translate(message,1)); 659*4887Schin #endif 660*4887Schin #endif 661*4887Schin } 662*4887Schin 663*4887Schin /* 664*4887Schin * change '['identifier']' to identifier 665*4887Schin * character before <str> must be a '[' 666*4887Schin * returns pointer to last character 667*4887Schin */ 668*4887Schin char *sh_checkid(char *str, char *last) 669*4887Schin { 670*4887Schin register unsigned char *cp = (unsigned char*)str; 671*4887Schin register unsigned char *v = cp; 672*4887Schin register int c; 673*4887Schin if(c= *cp++,isaletter(c)) 674*4887Schin while(c= *cp++,isaname(c)); 675*4887Schin if(c==']' && (!last || ((char*)cp==last))) 676*4887Schin { 677*4887Schin /* eliminate [ and ] */ 678*4887Schin while(v < cp) 679*4887Schin { 680*4887Schin v[-1] = *v; 681*4887Schin v++; 682*4887Schin } 683*4887Schin if(last) 684*4887Schin last -=2; 685*4887Schin else 686*4887Schin { 687*4887Schin while(*v) 688*4887Schin { 689*4887Schin v[-2] = *v; 690*4887Schin v++; 691*4887Schin } 692*4887Schin v[-2] = 0; 693*4887Schin last = (char*)v; 694*4887Schin } 695*4887Schin } 696*4887Schin return(last); 697*4887Schin } 698*4887Schin 699*4887Schin #if _AST_VERSION <= 20000317L 700*4887Schin char *fmtident(const char *string) 701*4887Schin { 702*4887Schin return((char*)string); 703*4887Schin } 704*4887Schin #endif 705