static char *fmtx(const char *string) { register const char *cp = string; register int n,c; unsigned char *state = (unsigned char*)sh_lexstates[2]; int offset = staktell(); if(*cp=='#' || *cp=='~') stakputc('\\'); while((c=mbchar(cp)),(c>UCHAR_MAX)||(n=state[c])==0 || n==S_EPAT); if(n==S_EOF && *string!='#') return((char*)string); stakwrite(string,--cp-string); for(string=cp;c=mbchar(cp);string=cp) { if((n=cp-string)==1) { if((n=state[c]) && n!=S_EPAT) stakputc('\\'); stakputc(c); } else stakwrite(string,n); } stakputc(0); return(stakptr(offset)); }
int _fcmbget(short *len) { static struct Extra extra; register int i, c, n; if(_Fcin.fcleft) { if((c = mbsize(extra.next)) < 0) c = 1; if((_Fcin.fcleft -= c) <=0) { _Fcin.fcptr = (unsigned char*)fcfirst() - _Fcin.fcleft; _Fcin.fcleft = 0; } *len = c; if(c==1) c = *extra.next++; else if(c==0) _Fcin.fcleft = 0; else c = mbchar(extra.next); return(c); } switch(*len = mbsize(_Fcin.fcptr)) { case -1: if(_Fcin._fcfile && (n=(_Fcin.fclast-_Fcin.fcptr)) < MB_LEN_MAX) { memcpy(extra.buff, _Fcin.fcptr, n); _Fcin.fcptr = _Fcin.fclast; for(i=n; i < MB_LEN_MAX+n; i++) { if((extra.buff[i] = fcgetc(c))==0) break; } _Fcin.fcleft = n; extra.next = extra.buff; return(fcmbget(len)); } *len = 1; /* fall through */ case 0: case 1: c=fcget(); break; default: c = mbchar(_Fcin.fcptr); } return(c); }
int sh_strchr(const char *string, register const char *dp) { wchar_t c, d; register const char *cp=string; mbinit(); d = mbchar(dp); mbinit(); while(c = mbchar(cp)) { if(c==d) return(cp-string); } if(d==0) return(cp-string); return(-1); }
int b_cut(int argc, char** argv, void* context) { register char* cp = 0; register Sfio_t* fp; char* s; int n; Cut_t* cut; int mode = 0; Delim_t wdelim; Delim_t ldelim; size_t reclen = 0; cmdinit(argc, argv, context, ERROR_CATALOG, 0); wdelim.chr = '\t'; ldelim.chr = '\n'; wdelim.len = ldelim.len = 1; for (;;) { switch (n = optget(argv, usage)) { case 0: break; case 'b': case 'c': if(mode&C_FIELDS) { error(2, "f option already specified"); continue; } cp = opt_info.arg; if(n=='b') mode |= C_BYTES; else mode |= C_CHARS; continue; case 'D': ldelim.str = opt_info.arg; if (mbwide()) { s = opt_info.arg; ldelim.chr = mbchar(s); if ((n = s - opt_info.arg) > 1) { ldelim.len = n; continue; } } ldelim.chr = *(unsigned char*)opt_info.arg; ldelim.len = 1; continue; case 'd': wdelim.str = opt_info.arg; if (mbwide()) { s = opt_info.arg; wdelim.chr = mbchar(s); if ((n = s - opt_info.arg) > 1) { wdelim.len = n; continue; } } wdelim.chr = *(unsigned char*)opt_info.arg; wdelim.len = 1; continue; case 'f': if(mode&(C_CHARS|C_BYTES)) { error(2, "c option already specified"); continue; } cp = opt_info.arg; mode |= C_FIELDS; continue; case 'n': mode |= C_NOSPLIT; continue; case 'N': mode |= C_NONEWLINE; continue; case 'R': case 'r': if(opt_info.num>0) reclen = opt_info.num; continue; case 's': mode |= C_SUPRESS; continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } argv += opt_info.index; if (error_info.errors) error(ERROR_usage(2), "%s",optusage(NiL)); if(!cp) { error(2, "b, c or f option must be specified"); error(ERROR_usage(2), "%s", optusage(NiL)); } if(!*cp) error(3, "non-empty b, c or f option must be specified"); if((mode & (C_FIELDS|C_SUPRESS)) == C_SUPRESS) error(3, "s option requires f option"); cut = cutinit(mode, cp, &wdelim, &ldelim, reclen); if(cp = *argv) argv++; do { if(!cp || streq(cp,"-")) fp = sfstdin; else if(!(fp = sfopen(NiL,cp,"r"))) { error(ERROR_system(0),"%s: cannot open",cp); continue; } if(mode&C_FIELDS) cutfields(cut,fp,sfstdout); else cutcols(cut,fp,sfstdout); if(fp!=sfstdin) sfclose(fp); } while(cp = *argv++); if (sfsync(sfstdout)) error(ERROR_system(0), "write error"); return error_info.errors != 0; }
int regcollate(register const char* s, char** e, char* buf, int size) { register int c; register char* u; register char* b; register char* x; register Ucs_map_t* a; Ucs_map_t* z; const char* t; const char* v; int n; int r; int ul; int term; wchar_t w[2]; Ucs_attr_t attr[3]; if (size < 2) r = -1; else if ((term = *s++) != '.' && term != '=') { s--; r = -1; } else if (*s == term && *(s + 1) == ']') r = -1; else { t = s; mbchar(s); if ((n = (s - t)) == 1) { if (*s == term && *(s + 1) == ']') { s += 2; r = -1; } else { if (!local.attrs && initialize()) return -1; attr[0] = attr[1] = attr[2] = 0; ul = 0; b = buf; x = buf + size - 2; r = 1; s = t; do { v = s; u = b; for (;;) { if (!(c = *s++)) return -1; if (c == term) { if (!(c = *s++)) return -1; if (c != term) { if (c != ']') return -1; r = -1; break; } } if (c == ' ' || c == '-' && u > b && *s != ' ' && *s != '-') break; if (isupper(c)) c = tolower(c); if (u > x) break; *u++ = c; } *u = 0; if (a = (Ucs_map_t*)dtmatch(local.attrs, b)) setattr(attr, a->code); else { if (u < x) *u++ = ' '; if (b == buf) { if (isupper(*v)) ul = UCS_UC; else if (islower(*v)) ul = UCS_LC; } b = u; } } while (r > 0); if (b > buf && *(b - 1) == ' ') b--; *b = 0; attr[0] &= ~((Ucs_attr_t)1); if (ul) { if (tstattr(attr, UCS_UC) || tstattr(attr, UCS_LC)) ul = 0; else setattr(attr, ul); } if (z = (Ucs_map_t*)dtmatch(local.names, buf)) for(;;) { for (a = z; a; a = a->next) if ((attr[0] & a->attr[0]) == attr[0] && (attr[1] & a->attr[1]) == attr[1] && (attr[2] & a->attr[2]) == attr[2]) { #if 0 if (a->code <= 0xff) { #if CC_NATIVE != CC_ASCII buf[0] = local.a2n[a->code]; #else buf[0] = a->code; #endif buf[r = 1] = 0; ul = 0; break; } #endif w[0] = a->code; w[1] = 0; if ((r = wcstombs(buf, w, size)) > 0) ul = 0; break; } if (!ul) break; clrattr(attr, ul); ul = 0; } } if (r < 0) { if ((n = s - t - 2) > (size - 1)) return -1; memcpy(buf, t, n); buf[n] = 0; if (n == 1) r = n; else { for (t = buf; isalnum(*t); t++); if (!*t) r = n; } } } else if (*s++ != term || *s++ != ']') { s--; r = -1; } else if (n > (size - 1)) r = -1; else { memcpy(buf, t, n); buf[r = n] = 0; } } if (e) *e = (char*)s; return r; }
/* * put <string> of length <nbyte> onto lookahead stack * if <type> is non-zero, the negation of the character is put * onto the stack so that it can be checked for KEYTRAP * putstack() returns 1 except when in the middle of a multi-byte char */ static int putstack(Edit_t *ep,char string[], register int nbyte, int type) { register int c; #if SHOPT_MULTIBYTE char *endp, *p=string; int size, offset = ep->e_lookahead + nbyte; *(endp = &p[nbyte]) = 0; endp = &p[nbyte]; do { c = (int)((*p) & STRIP); if(c< 0x80 && c!='<') { if (type) c = -c; # ifndef CBREAK if(c == '\0') { /*** user break key ***/ ep->e_lookahead = 0; # if KSHELL sh_fault(SIGINT); siglongjmp(ep->e_env, UINTR); # endif /* KSHELL */ } # endif /* CBREAK */ } else { again: if((c=mbchar(p)) >=0) { p--; /* incremented below */ if(type) c = -c; } #ifdef EILSEQ else if(errno == EILSEQ) errno = 0; #endif else if((endp-p) < mbmax()) { if ((c=ed_read(ep,ep->e_fd,endp, 1,0)) == 1) { *++endp = 0; goto again; } return(c); } else { ed_ringbell(); c = -(int)((*p) & STRIP); offset += mbmax()-1; } } ep->e_lbuf[--offset] = c; p++; } while (p < endp); /* shift lookahead buffer if necessary */ if(offset -= ep->e_lookahead) { for(size=offset;size < nbyte;size++) ep->e_lbuf[ep->e_lookahead+size-offset] = ep->e_lbuf[ep->e_lookahead+size]; } ep->e_lookahead += nbyte-offset; #else while (nbyte > 0) { c = string[--nbyte] & STRIP; ep->e_lbuf[ep->e_lookahead++] = (type?-c:c); # ifndef CBREAK if( c == '\0' ) { /*** user break key ***/ ep->e_lookahead = 0; # if KSHELL sh_fault(SIGINT); siglongjmp(ep->e_env, UINTR); # endif /* KSHELL */ } # endif /* CBREAK */ } #endif /* SHOPT_MULTIBYTE */ return(1); }
void ed_setup(register Edit_t *ep, int fd, int reedit) { Shell_t *shp = ep->sh; register char *pp; register char *last, *prev; char *ppmax; int myquote = 0, n; register int qlen = 1, qwid; char inquote = 0; ep->e_fd = fd; ep->e_multiline = sh_isoption(SH_MULTILINE)!=0; #ifdef SIGWINCH if(!(shp->sigflag[SIGWINCH]&SH_SIGFAULT)) { signal(SIGWINCH,sh_fault); shp->sigflag[SIGWINCH] |= SH_SIGFAULT; } pp = shp->st.trapcom[SIGWINCH]; shp->st.trapcom[SIGWINCH] = 0; sh_fault(SIGWINCH); shp->st.trapcom[SIGWINCH] = pp; ep->sh->winch = 0; #endif #if SHOPT_EDPREDICT ep->hlist = 0; ep->nhlist = 0; ep->hoff = 0; #endif /* SHOPT_EDPREDICT */ #if KSHELL ep->e_stkptr = stakptr(0); ep->e_stkoff = staktell(); if(!(last = shp->prompt)) last = ""; shp->prompt = 0; #else last = ep->e_prbuff; #endif /* KSHELL */ if(shp->gd->hist_ptr) { register History_t *hp = shp->gd->hist_ptr; ep->e_hismax = hist_max(hp); ep->e_hismin = hist_min(hp); } else { ep->e_hismax = ep->e_hismin = ep->e_hloff = 0; } ep->e_hline = ep->e_hismax; if(!sh_isoption(SH_VI) && !sh_isoption(SH_EMACS) && !sh_isoption(SH_GMACS)) ep->e_wsize = MAXLINE; else ep->e_wsize = ed_window()-2; ep->e_winsz = ep->e_wsize+2; ep->e_crlf = 1; ep->e_plen = 0; pp = ep->e_prompt; ppmax = pp+PRSIZE-1; *pp++ = '\r'; { register int c; while(prev = last, c = mbchar(last)) switch(c) { case ESC: { int skip=0; ep->e_crlf = 0; *pp++ = c; for(n=1; c = *last++; n++) { if(pp < ppmax) *pp++ = c; if(c=='\a' || c==ESC || c=='\r') break; if(skip || (c>='0' && c<='9')) { skip = 0; continue; } if(n>1 && c==';') skip = 1; else if(n>2 || (c!= '[' && c!= ']')) break; } if(c==0 || c==ESC || c=='\r') last--; qlen += (n+1); break; } case '\b': if(pp>ep->e_prompt+1) pp--; break; case '\r': if(pp == (ep->e_prompt+2)) /* quote char */ myquote = *(pp-1); /*FALLTHROUGH*/ case '\n': /* start again */ ep->e_crlf = 1; qlen = 1; inquote = 0; pp = ep->e_prompt+1; break; case '\t': /* expand tabs */ while((pp-ep->e_prompt)%TABSIZE) { if(pp >= ppmax) break; *pp++ = ' '; } break; case '\a': /* cut out bells */ break; default: if(c==myquote) { qlen += inquote; inquote ^= 1; } if(pp < ppmax) { if(inquote) qlen++; else if(!is_print(c)) ep->e_crlf = 0; if((qwid = last - prev) > 1) qlen += qwid - mbwidth(c); while(prev < last && pp < ppmax) *pp++ = *prev++; } break; } } if(pp-ep->e_prompt > qlen) ep->e_plen = pp - ep->e_prompt - qlen; *pp = 0; if(!ep->e_multiline && (ep->e_wsize -= ep->e_plen) < 7) { register int shift = 7-ep->e_wsize; ep->e_wsize = 7; pp = ep->e_prompt+1; strcpy(pp,pp+shift); ep->e_plen -= shift; last[-ep->e_plen-2] = '\r'; } sfsync(sfstderr); if(fd == sffileno(sfstderr)) { /* can't use output buffer when reading from stderr */ static char *buff; if(!buff) buff = (char*)malloc(MAXLINE); ep->e_outbase = ep->e_outptr = buff; ep->e_outlast = ep->e_outptr + MAXLINE; return; } qlen = sfset(sfstderr,SF_READ,0); /* make sure SF_READ not on */ ep->e_outbase = ep->e_outptr = (char*)sfreserve(sfstderr,SF_UNBOUND,SF_LOCKR); ep->e_outlast = ep->e_outptr + sfvalue(sfstderr); if(qlen) sfset(sfstderr,SF_READ,1); sfwrite(sfstderr,ep->e_outptr,0); ep->e_eol = reedit; if(ep->e_multiline) { #ifdef _cmd_tput char *term; if(!ep->e_term) ep->e_term = nv_search("TERM",shp->var_tree,0); if(ep->e_term && (term=nv_getval(ep->e_term)) && strlen(term)<sizeof(ep->e_termname) && strcmp(term,ep->e_termname)) { sh_trap(".sh.subscript=$(tput cuu1 2>/dev/null)",0); if(pp=nv_getval(SH_SUBSCRNOD)) strncpy(CURSOR_UP,pp,sizeof(CURSOR_UP)-1); nv_unset(SH_SUBSCRNOD); strcpy(ep->e_termname,term); } #endif ep->e_wsize = MAXLINE - (ep->e_plen+1); } if(ep->e_default && (pp = nv_getval(ep->e_default))) { n = strlen(pp); if(n > LOOKAHEAD) n = LOOKAHEAD; ep->e_lookahead = n; while(n-- > 0) ep->e_lbuf[n] = *pp++; ep->e_default = 0; } }
int b_paste(int argc, char** argv, Shbltin_t* context) { register int n, sflag=0; register Sfio_t *fp, **streams; register char *cp, *delim; char *ep; Delim_t *mp; int dlen, dsiz; char defdelim[2]; cmdinit(argc, argv, context, ERROR_CATALOG, 0); delim = 0; for (;;) { switch (optget(argv, usage)) { case 'd': delim = opt_info.arg; continue; case 's': sflag++; continue; case ':': error(2, "%s", opt_info.arg); break; case '?': error(ERROR_usage(2), "%s", opt_info.arg); break; } break; } argv += opt_info.index; if(error_info.errors) error(ERROR_usage(2),"%s", optusage(NiL)); if(!delim || !*delim) { delim = defdelim; delim[0] = '\t'; delim[1] = 0; } if (!(delim = strdup(delim))) error(ERROR_system(1), "out of space"); dlen = dsiz = stresc(delim); mp = 0; if (mbwide()) { cp = delim; ep = delim + dlen; dlen = 0; while (cp < ep) { mbchar(cp); dlen++; } if(dlen < dsiz) { if (!(mp = newof(0, Delim_t, dlen, 0))) { free(delim); error(ERROR_system(1), "out of space"); } cp = delim; dlen = 0; while (cp < ep) { mp[dlen].chr = cp; mbchar(cp); mp[dlen].len = cp - mp[dlen].chr; dlen++; } } } if(cp = *argv) { n = argc - opt_info.index; argv++; } else n = 1; if(!sflag) { if (!(streams = (Sfio_t**)stakalloc(n*sizeof(Sfio_t*)))) error(ERROR_exit(1), "out of space"); n = 0; } do { if(!cp || streq(cp,"-")) fp = sfstdin; else if(!(fp = sfopen(NiL,cp,"r"))) error(ERROR_system(0),"%s: cannot open",cp); if(fp && sflag) { if(spaste(fp,sfstdout,delim,dsiz,dlen,mp) < 0) error(ERROR_system(0),"write failed"); if(fp!=sfstdin) sfclose(fp); } else if(!sflag) streams[n++] = fp; } while(cp= *argv++); if(!sflag) { if(error_info.errors==0 && paste(n,streams,sfstdout,delim,dsiz,dlen,mp) < 0) error(ERROR_system(0),"write failed"); while(--n>=0) if((fp=streams[n]) && fp!=sfstdin) sfclose(fp); } if (mp) free(mp); free(delim); return(error_info.errors); }
/* * returns pointer to beginning of expansion and sets type of expansion */ static char *find_begin(char outbuff[], char *last, int endchar, int *type) { register char *cp=outbuff, *bp, *xp; register int c,inquote = 0, inassign=0; int mode=*type; bp = outbuff; *type = 0; while(cp < last) { xp = cp; switch(c= mbchar(cp)) { case '\'': case '"': if(!inquote) { inquote = c; bp = xp; break; } if(inquote==c) inquote = 0; break; case '\\': if(inquote != '\'') mbchar(cp); break; case '$': if(inquote == '\'') break; c = *(unsigned char*)cp; if(mode!='*' && (isaletter(c) || c=='{')) { int dot = '.'; if(c=='{') { xp = cp; mbchar(cp); c = *(unsigned char*)cp; if(c!='.' && !isaletter(c)) break; } else dot = 'a'; while(cp < last) { if((c= mbchar(cp)) , c!=dot && !isaname(c)) break; } if(cp>=last) { if(c==dot || isaname(c)) { *type='$'; return(++xp); } if(c!='}') bp = cp; } } else if(c=='(') { *type = mode; xp = find_begin(cp,last,')',type); if(*(cp=xp)!=')') bp = xp; else cp++; } break; case '=': if(!inquote) { bp = cp; inassign = 1; } break; case ':': if(!inquote && inassign) bp = cp; break; case '~': if(*cp=='(') break; /* fall through */ default: if(c && c==endchar) return(xp); if(!inquote && ismeta(c)) { bp = cp; inassign = 0; } break; } } if(inquote && *bp==inquote) *type = *bp++; return(bp); }
int ed_expand(Edit_t *ep, char outbuff[],int *cur,int *eol,int mode, int count) { struct comnod *comptr; struct argnod *ap; register char *out; char *av[2], *begin , *dir=0; int addstar=0, rval=0, var=0, strip=1; int nomarkdirs = !sh_isoption(SH_MARKDIRS); sh_onstate(SH_FCOMPLETE); if(ep->e_nlist) { if(mode=='=' && count>0) { if(count> ep->e_nlist) return(-1); mode = '?'; av[0] = ep->e_clist[count-1]; av[1] = 0; } else { stakset(ep->e_stkptr,ep->e_stkoff); ep->e_nlist = 0; } } comptr = (struct comnod*)stakalloc(sizeof(struct comnod)); ap = (struct argnod*)stakseek(ARGVAL); #if SHOPT_MULTIBYTE { register int c = *cur; register genchar *cp; /* adjust cur */ cp = (genchar *)outbuff + *cur; c = *cp; *cp = 0; *cur = ed_external((genchar*)outbuff,(char*)stakptr(0)); *cp = c; *eol = ed_external((genchar*)outbuff,outbuff); } #endif /* SHOPT_MULTIBYTE */ out = outbuff + *cur + (sh_isoption(SH_VI)!=0); if(out[-1]=='"' || out[-1]=='\'') { rval = -(sh_isoption(SH_VI)!=0); goto done; } comptr->comtyp = COMSCAN; comptr->comarg = ap; ap->argflag = (ARG_MAC|ARG_EXP); ap->argnxt.ap = 0; ap->argchn.cp = 0; { register int c; char *last = out; c = *(unsigned char*)out; var = mode; begin = out = find_begin(outbuff,last,0,&var); /* addstar set to zero if * should not be added */ if(var=='$') { stakputs("${!"); stakwrite(out,last-out); stakputs("@}"); out = last; } else { addstar = '*'; while(out < last) { c = *(unsigned char*)out; if(isexp(c)) addstar = 0; if (c == '/') { if(addstar == 0) strip = 0; dir = out+1; } stakputc(c); out++; } } if(mode=='?') mode = '*'; if(var!='$' && mode=='\\' && out[-1]!='*') addstar = '*'; if(*begin=='~' && !strchr(begin,'/')) addstar = 0; stakputc(addstar); ap = (struct argnod*)stakfreeze(1); } if(mode!='*') sh_onoption(SH_MARKDIRS); { register char **com; char *cp=begin, *left=0, *saveout="."; int nocase=0,narg,cmd_completion=0; register int size='x'; while(cp>outbuff && ((size=cp[-1])==' ' || size=='\t')) cp--; if(!var && !strchr(ap->argval,'/') && (((cp==outbuff&&ep->sh->nextprompt==1) || (strchr(";&|(",size)) && (cp==outbuff+1||size=='('||cp[-2]!='>') && *begin!='~' ))) { cmd_completion=1; sh_onstate(SH_COMPLETE); } if(ep->e_nlist) { narg = 1; com = av; if(dir) begin += (dir-begin); } else { com = sh_argbuild(ep->sh,&narg,comptr,0); /* special handling for leading quotes */ if(begin>outbuff && (begin[-1]=='"' || begin[-1]=='\'')) begin--; } sh_offstate(SH_COMPLETE); /* allow a search to be aborted */ if(ep->sh->trapnote&SH_SIGSET) { rval = -1; goto done; } /* match? */ if (*com==0 || (narg <= 1 && (strcmp(ap->argval,*com)==0) || (addstar && com[0][strlen(*com)-1]=='*'))) { rval = -1; goto done; } if(mode=='\\' && out[-1]=='/' && narg>1) mode = '='; if(mode=='=') { if (strip && !cmd_completion) { register char **ptrcom; for(ptrcom=com;*ptrcom;ptrcom++) /* trim directory prefix */ *ptrcom = path_basename(*ptrcom); } sfputc(sfstderr,'\n'); sh_menu(sfstderr,narg,com); sfsync(sfstderr); ep->e_nlist = narg; ep->e_clist = com; goto done; } /* see if there is enough room */ size = *eol - (out-begin); if(mode=='\\') { int c; if(dir) { c = *dir; *dir = 0; saveout = begin; } if(saveout=astconf("PATH_ATTRIBUTES",saveout,(char*)0)) nocase = (strchr(saveout,'c')!=0); if(dir) *dir = c; /* just expand until name is unique */ size += strlen(*com); } else { size += narg; { char **savcom = com; while (*com) size += strlen(cp=fmtx(*com++)); com = savcom; } } /* see if room for expansion */ if(outbuff+size >= &outbuff[MAXLINE]) { com[0] = ap->argval; com[1] = 0; } /* save remainder of the buffer */ if(*out) left=stakcopy(out); if(cmd_completion && mode=='\\') out = strcopy(begin,path_basename(cp= *com++)); else if(mode=='*') { if(ep->e_nlist && dir && var) { if(*cp==var) cp++; else *begin++ = var; out = strcopy(begin,cp); var = 0; } else out = strcopy(begin,fmtx(*com)); com++; } else out = strcopy(begin,*com++); if(mode=='\\') { saveout= ++out; while (*com && *begin) { if(cmd_completion) out = overlaid(begin,path_basename(*com++),nocase); else out = overlaid(begin,*com++,nocase); } mode = (out==saveout); if(out[-1]==0) out--; if(mode && out[-1]!='/') { if(cmd_completion) { Namval_t *np; /* add as tracked alias */ Pathcomp_t *pp; if(*cp=='/' && (pp=path_dirfind(ep->sh->pathlist,cp,'/')) && (np=nv_search(begin,ep->sh->track_tree,NV_ADD))) path_alias(np,pp); out = strcopy(begin,cp); } /* add quotes if necessary */ if((cp=fmtx(begin))!=begin) out = strcopy(begin,cp); if(var=='$' && begin[-1]=='{') *out = '}'; else *out = ' '; *++out = 0; } else if((cp=fmtx(begin))!=begin) { out = strcopy(begin,cp); if(out[-1] =='"' || out[-1]=='\'') *--out = 0; } if(*begin==0) ed_ringbell(); } else { while (*com) { *out++ = ' '; out = strcopy(out,fmtx(*com++)); } } if(ep->e_nlist) { cp = com[-1]; if(cp[strlen(cp)-1]!='/') { if(var=='$' && begin[-1]=='{') *out = '}'; else *out = ' '; out++; } else if(out[-1] =='"' || out[-1]=='\'') out--; *out = 0; } *cur = (out-outbuff); /* restore rest of buffer */ if(left) out = strcopy(out,left); *eol = (out-outbuff); } done: sh_offstate(SH_FCOMPLETE); if(!ep->e_nlist) stakset(ep->e_stkptr,ep->e_stkoff); if(nomarkdirs) sh_offoption(SH_MARKDIRS); #if SHOPT_MULTIBYTE { register int c,n=0; /* first re-adjust cur */ c = outbuff[*cur]; outbuff[*cur] = 0; for(out=outbuff; *out;n++) mbchar(out); outbuff[*cur] = c; *cur = n; outbuff[*eol+1] = 0; *eol = ed_internal(outbuff,(genchar*)outbuff); } #endif /* SHOPT_MULTIBYTE */ return(rval); }
int wc_count(Wc_t *wp, Sfio_t *fd, const char* file) { register char* type = wp->type; register unsigned char* cp; register Sfoff_t nbytes; register Sfoff_t nchars; register Sfoff_t nwords; register Sfoff_t nlines; register Sfoff_t eline = -1; register Sfoff_t longest = 0; register ssize_t c; register unsigned char* endbuff; register int lasttype = WC_SP; unsigned int lastchar; ssize_t n; ssize_t o; unsigned char* buff; wchar_t x; unsigned char side[32]; sfset(fd,SF_WRITE,1); nlines = nwords = nchars = nbytes = 0; wp->longest = 0; if (wp->mb < 0 && (wp->mode & (WC_MBYTE|WC_WORDS))) { cp = buff = endbuff = 0; for (;;) { if (cp >= endbuff || (n = mb2wc(x, cp, endbuff-cp)) < 0) { if ((o = endbuff-cp) < sizeof(side)) { if (buff) { if (o) memcpy(side, cp, o); mbinit(); } else o = 0; cp = side + o; if (!(buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) || (n = sfvalue(fd)) <= 0) { if ((nchars - longest) > wp->longest) wp->longest = nchars - longest; break; } nbytes += n; if ((c = sizeof(side) - o) > n) c = n; if (c) memcpy(cp, buff, c); endbuff = buff + n; cp = side; x = mbchar(cp); if ((cp-side) < o) { cp = buff; nchars += (cp-side) - 1; } else cp = buff + (cp-side) - o; } else { cp++; x = -1; } if (x == -1 && eline != nlines && !(wp->mode & WC_QUIET)) eline = invalid(file, nlines); } else cp += n ? n : 1; if (x == '\n') { if ((nchars - longest) > wp->longest) wp->longest = nchars - longest; longest = nchars + 1; nlines++; lasttype = 1; } else if (iswspace(x)) lasttype = 1; else if (lasttype) { lasttype = 0; nwords++; } nchars++; } if (!(wp->mode & WC_MBYTE)) nchars = nbytes; } else if (!wp->mb && !(wp->mode & WC_LONGEST) || wp->mb > 0 && !(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST))) { if (!(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST))) { while ((cp = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0) { nchars += c; endbuff = cp + c; if (*--endbuff == '\n') nlines++; else *endbuff = '\n'; for (;;) if (*cp++ == '\n') { if (cp > endbuff) break; nlines++; } } } else { while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0) { nchars += c; /* check to see whether first character terminates word */ if (c==1) { if (eol(lasttype)) nlines++; if ((c = type[*cp]) && !lasttype) nwords++; lasttype = c; continue; } if (!lasttype && type[*cp]) nwords++; lastchar = cp[--c]; *(endbuff = cp+c) = '\n'; c = lasttype; /* process each buffer */ for (;;) { /* process spaces and new-lines */ do { if (eol(c)) for (;;) { /* check for end of buffer */ if (cp > endbuff) goto beob; nlines++; if (*cp != '\n') break; cp++; } } while (c = type[*cp++]); /* skip over word characters */ while (!(c = type[*cp++])); nwords++; } beob: if ((cp -= 2) >= buff) c = type[*cp]; else c = lasttype; lasttype = type[lastchar]; /* see if was in word */ if (!c && !lasttype) nwords--; } if (eol(lasttype)) nlines++; else if (!lasttype) nwords++; } } else { int lineoff=0; int skip=0; int adjust=0; int state=0; int oldc; int xspace; int wasspace = 1; unsigned char* start; lastchar = 0; start = (endbuff = side) + 1; xspace = iswspace(0xa0) || iswspace(0x85); while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0) { nbytes += c; nchars += c; start = cp-lineoff; /* check to see whether first character terminates word */ if(c==1) { if(eol(lasttype)) nlines++; if((c = type[*cp]) && !lasttype) nwords++; lasttype = c; endbuff = start; continue; } lastchar = cp[--c]; endbuff = cp+c; cp[c] = '\n'; if(mbc(lasttype)) { c = lasttype; goto mbyte; } if(!lasttype && spc(type[*cp])) nwords++; c = lasttype; /* process each buffer */ for (;;) { /* process spaces and new-lines */ spaces: do { if (eol(c)) { /* check for end of buffer */ if (cp > endbuff) goto eob; if(wp->mode&WC_LONGEST) { if((cp-start)-adjust > longest) longest = (cp-start)-adjust-1; start = cp; } nlines++; nchars -= adjust; adjust = 0; } } while (spc(c = type[*cp++])); wasspace=1; if(mbc(c)) { mbyte: do { if(c&WC_ERR) goto err; if(skip && (c&7)) break; if(!skip) { if(!(c&7)) { skip=1; break; } skip = (c&7); adjust += skip; state = 0; if(skip==2 && (cp[-1]&0xc)==0 && (state=(cp[-1]&0x3))) oldc = *cp; else if(xspace && cp[-1]==0xc2) { state = 8; oldc = *cp; } } else { skip--; if(state && (state=chkstate(state,oldc))) { if(state==10) { if(!wasspace) nwords++; wasspace = 1; state=0; goto spaces; } oldc = *cp; } } } while (mbc(c = type[*cp++])); wasspace = 0; if(skip) { if(eol(c) && (cp > endbuff)) goto eob; err: skip = 0; state = 0; if(eline!=nlines && !(wp->mode & WC_QUIET)) eline = invalid(file, nlines); while(mbc(c) && ((c|WC_ERR) || (c&7)==0)) c=type[*cp++]; if(eol(c) && (cp > endbuff)) { c = WC_MB|WC_ERR; goto eob; } if(mbc(c)) goto mbyte; else if(c&WC_SP) goto spaces; } if(spc(c)) { nwords++; continue; } } /* skip over word characters */ while(!(c = type[*cp++])); if(mbc(c)) goto mbyte; nwords++; } eob: lineoff = cp-start; if((cp -= 2) >= buff) c = type[*cp]; else c = lasttype; lasttype = type[lastchar]; /* see if was in word */ if(!c && !lasttype) nwords--; } if ((wp->mode&WC_LONGEST) && ((endbuff + 1 - start) - adjust - (lastchar == '\n')) > longest) longest = (endbuff + 1 - start) - adjust - (lastchar == '\n'); wp->longest = longest; if (eol(lasttype)) nlines++; else if (!lasttype) nwords++; if (wp->mode & WC_MBYTE) nchars -= adjust; else nchars = nbytes; } wp->chars = nchars; wp->words = nwords; wp->lines = nlines; return 0; }
char* fmtquote(const char* as, const char* qb, const char* qe, size_t n, int flags) { register unsigned char* s = (unsigned char*)as; register unsigned char* e = s + n; register char* b; register int c; register int m; register int escaped; register int spaced; register int doublequote; register int singlequote; int shell; char* f; char* buf; c = 4 * (n + 1); if (qb) c += strlen((char*)qb); if (qe) c += strlen((char*)qe); b = buf = fmtbuf(c); shell = 0; doublequote = 0; singlequote = 0; if (qb) { if (qb[0] == '$' && qb[1] == '\'' && qb[2] == 0) shell = 1; else if ((flags & FMT_SHELL) && qb[1] == 0) { if (qb[0] == '"') doublequote = 1; else if (qb[0] == '\'') singlequote = 1; } while (*b = *qb++) b++; } else if (flags & FMT_SHELL) doublequote = 1; f = b; escaped = spaced = !!(flags & FMT_ALWAYS); while (s < e) { if ((m = mbsize(s)) > 1 && (s + m) <= e) { #if _hdr_wchar && _hdr_wctype c = mbchar(s); if (!spaced && !escaped && (iswspace(c) || iswcntrl(c))) spaced = 1; s -= m; #endif while (m--) *b++ = *s++; } else { c = *s++; if (!(flags & FMT_ESCAPED) && (iscntrl(c) || !isprint(c) || c == '\\')) { escaped = 1; *b++ = '\\'; switch (c) { case CC_bel: c = 'a'; break; case '\b': c = 'b'; break; case '\f': c = 'f'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case CC_vt: c = 'v'; break; case CC_esc: c = 'E'; break; case '\\': break; default: if (!(flags & FMT_WIDE) || !(c & 0200)) { *b++ = '0' + ((c >> 6) & 07); *b++ = '0' + ((c >> 3) & 07); c = '0' + (c & 07); } else b--; break; } }
int chrexp(register const char* s, char** p, int* m, register int flags) { register const char* q; register int c; const char* e; const char* b; char* r; int n; int w; w = 0; for (;;) { b = s; switch (c = mbchar(s)) { case 0: s--; break; case '\\': switch (c = *s++) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c -= '0'; q = s + 2; while (s < q) switch (*s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = (c << 3) + *s++ - '0'; break; default: q = s; break; } break; case 'a': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_bel; break; case 'b': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\b'; break; case 'c': /*DEPRECATED*/ case 'C': if (!(flags & FMT_EXP_CHAR)) goto noexpand; if (c = *s) { s++; if (c == '\\') { c = chrexp(s - 1, &r, 0, flags); s = (const char*)r; } if (islower(c)) c = toupper(c); c = ccmapc(c, CC_NATIVE, CC_ASCII); c ^= 0x40; c = ccmapc(c, CC_ASCII, CC_NATIVE); } break; case 'e': /*DEPRECATED*/ case 'E': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_esc; break; case 'f': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\f'; break; case 'M': if (!(flags & FMT_EXP_CHAR)) goto noexpand; if (*s == '-') { s++; c = CC_esc; } break; case 'n': if (flags & FMT_EXP_NONL) continue; if (!(flags & FMT_EXP_LINE)) goto noexpand; c = '\n'; break; case 'r': if (flags & FMT_EXP_NOCR) continue; if (!(flags & FMT_EXP_LINE)) goto noexpand; c = '\r'; break; case 't': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\t'; break; case 'v': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_vt; break; case 'u': case 'U': case 'x': if (q = c == 'u' ? (s + 4) : c == 'U' ? (s + 8) : (char*)0) { if (!(flags & FMT_EXP_WIDE)) goto noexpand; w = 1; } b = e = s; n = 0; c = 0; while (!e || !q || s < q) { switch (*s) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c = (c << 4) + *s++ - 'a' + 10; n++; continue; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c = (c << 4) + *s++ - 'A' + 10; n++; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c = (c << 4) + *s++ - '0'; n++; continue; case '{': case '[': if (s != e) break; e = 0; s++; continue; case '}': case ']': if (!e) s++; break; default: break; } break; } if (n <= 2 && !(flags & FMT_EXP_CHAR) || n > 2 && (w = 1) && !(flags & FMT_EXP_WIDE)) { c = '\\'; s = b; } break; case 0: s--; break; } break; default: if ((s - b) > 1) w = 1; break; } break; } normal: if (p) *p = (char*)s; if (m) *m = w; return c; noexpand: c = '\\'; s--; goto normal; }
int chrexp(const char *s, char **p, int *m, int flags) { const char *t; int c; const char *e; const char *b; char *r; int n; int x; wchar_t d; Mbstate_t q; bool u; bool w; u = w = 0; mbinit(&q); for (;;) { b = s; c = mbchar(&d, (char **)&s, MB_LEN_MAX, &q); switch (c) { case 0: s = b; break; case '\\': b = s; switch (c = *s++) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c -= '0'; t = s + 2; while (s < t) { switch (*s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = (c << 3) + *s++ - '0'; break; default: t = s; break; } } break; case 'a': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_bel; break; case 'b': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\b'; break; case 'c': /*DEPRECATED*/ case 'C': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = *s; if (c) { s++; if (c == '\\') { c = chrexp(s - 1, &r, 0, flags); s = (const char *)r; } if (islower(c)) c = toupper(c); c ^= 0x40; } break; case 'e': /*DEPRECATED*/ case 'E': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_esc; break; case 'f': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\f'; break; case 'M': if (!(flags & FMT_EXP_CHAR)) goto noexpand; if (*s == '-') { s++; c = CC_esc; } break; case 'n': if (flags & FMT_EXP_NONL) continue; if (!(flags & FMT_EXP_LINE)) goto noexpand; c = '\n'; break; case 'r': if (flags & FMT_EXP_NOCR) continue; if (!(flags & FMT_EXP_LINE)) goto noexpand; c = '\r'; break; case 't': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = '\t'; break; case 'v': if (!(flags & FMT_EXP_CHAR)) goto noexpand; c = CC_vt; break; case 'u': u = 1; // FALLTHRU case 'w': t = s + 4; goto wex; case 'U': u = 1; // FALLTHRU case 'W': t = s + 8; wex: if (!(flags & FMT_EXP_WIDE)) goto noexpand; w = 1; goto hex; case 'x': t = s + 2; hex: e = s; n = 0; c = 0; x = 0; while (!e || !t || s < t) { switch (*s) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': c = (c << 4) + *s++ - 'a' + 10; n++; continue; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': c = (c << 4) + *s++ - 'A' + 10; n++; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c = (c << 4) + *s++ - '0'; n++; continue; case '{': case '[': if (s != e) break; e = 0; s++; if (w && (*s == 'U' || *s == 'W') && *(s + 1) == '+') s += 2; continue; case '-': if (e) break; if (*(s + 1) != '}' && *(s + 1) != ']') { if (!*(s + 1) || (*(s + 2) != '}' && *(s + 2) != ']')) { break; } x = *(unsigned char *)(s + 1); s += 2; } else { x = -1; s++; } /*FALLTHROUGH*/ case '}': case ']': if (!e) e = ++s; break; default: break; } break; } if (e) { if (n < 8 || (n == 8 && c >= 0)) { if (!w) { if (n > 2) { if (!(flags & FMT_EXP_WIDE)) goto noexpand; w = 1; } else if (!(flags & FMT_EXP_CHAR)) { goto noexpand; } else { break; } } if (!mbwide()) w = 0; if (c <= 0x7f) break; if (u) { uint32_t i = c; wchar_t o; if (!utf32invalid(i) && utf32stowcs(&o, &i, 1) > 0) { c = o; break; } } else if (w || c <= ast.byte_max) { break; } } if (x) { c = x; w = 0; break; } } /*FALLTHROUGH*/ case 0: goto noexpand; } break; default: if ((s - b) > 1) w = 1; break; noexpand: s = b; w = 0; c = '\\'; break; } break; } if (m) *m = w; if (p) *p = (char *)s; return c; }
/* * print <str> quoting chars so that it can be read by the shell * puts null terminated result on stack, but doesn't freeze it * single!=0 limits quoting to '...' * fold>0 prints raw newlines and inserts appropriately * escaped newlines every (fold-x) chars */ char *sh_fmtqf(const char *string, int single, int fold) { register const char *cp = string; register const char *bp; register const char *vp; register int c; register int n; register int q; register int a; int offset; if (--fold < 8) fold = 0; if (!cp || !*cp || !single && !fold || fold && strlen(string) < fold) return sh_fmtq(cp); offset = staktell(); single = single ? 1 : 3; c = mbchar(string); a = isaletter(c) ? '=' : 0; vp = cp + 1; do { q = 0; n = fold; bp = cp; while ((!n || n-- > 0) && (c = mbchar(cp))) { if (a && !isaname(c)) a = 0; #if SHOPT_MULTIBYTE if (c >= 0x200) continue; if (c == '\'' || !iswprint(c)) #else if (c == '\'' || !isprint(c)) #endif /* SHOPT_MULTIBYTE */ { q = single; break; } if (c == '\n') q = 1; else if (c == a) { stakwrite(bp, cp - bp); bp = cp; vp = cp + 1; a = 0; } else if ((c == '#' || c == '~') && cp == vp || c == ']' || c != ':' && (c = sh_lexstates[ST_NORM][c]) && c != S_EPAT) q = 1; } if (q & 2) { stakputc('$'); stakputc('\''); cp = bp; n = fold - 3; q = 1; while (c = mbchar(cp)) { switch (c) { case ('a'==97?'\033':39): c = 'E'; break; case '\n': q = 0; n = fold - 1; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case '\f': c = 'f'; break; case '\b': c = 'b'; break; case '\a': c = 'a'; break; case '\\': if (*cp == 'n') { c = '\n'; q = 0; n = fold - 1; break; } case '\'': break; default: #if SHOPT_MULTIBYTE if(!iswprint(c)) #else if(!isprint(c)) #endif { if ((n -= 4) <= 0) { stakwrite("'\\\n$'", 5); n = fold - 7; } sfprintf(staksp, "\\%03o", c); continue; } q = 0; break; } if ((n -= q + 1) <= 0) { if (!q) { stakputc('\''); cp = bp; break; } stakwrite("'\\\n$'", 5); n = fold - 5; } if (q) stakputc('\\'); else q = 1; stakputc(c); bp = cp; } if (!c) stakputc('\''); } else if (q & 1) { stakputc('\''); cp = bp; n = fold ? (fold - 2) : 0; while (c = mbchar(cp)) { if (c == '\n') n = fold - 1; else if (n && --n <= 0) { n = fold - 2; stakwrite(bp, --cp - bp); bp = cp; stakwrite("'\\\n'", 4); } else if (n == 1 && *cp == '\'') { n = fold - 5; stakwrite(bp, --cp - bp); bp = cp; stakwrite("'\\\n\\''", 6); } else if (c == '\'') { stakwrite(bp, cp - bp - 1); bp = cp; if (n && (n -= 4) <= 0) { n = fold - 5; stakwrite("'\\\n\\''", 6); } else stakwrite("'\\''", 4); } } stakwrite(bp, cp - bp - 1); stakputc('\''); } else if (n = fold) { cp = bp; while (c = mbchar(cp)) { if (--n <= 0) { n = fold; stakwrite(bp, --cp - bp); bp = cp; stakwrite("\\\n", 2); } } stakwrite(bp, cp - bp - 1); } else stakwrite(bp, cp - bp); if (c) { stakputc('\\'); stakputc('\n'); } } while (c); stakputc(0); return(stakptr(offset)); }
/* * print <str> quoting chars so that it can be read by the shell * puts null terminated result on stack, but doesn't freeze it */ char *sh_fmtq(const char *string) { register const char *cp = string, *op; register int c, state; int offset; if(!cp) return((char*)0); offset = staktell(); #if SHOPT_MULTIBYTE state = ((c= mbchar(cp))==0); #else state = ((c= *(unsigned char*)cp++)==0); #endif if(isaletter(c)) { #if SHOPT_MULTIBYTE while((c=mbchar(cp)),isaname(c)); #else while((c = *(unsigned char*)cp++),isaname(c)); #endif if(c==0) return((char*)string); if(c=='=') { if(*cp==0) return((char*)string); c = cp - string; stakwrite(string,c); string = cp; #if SHOPT_MULTIBYTE c = mbchar(cp); #else c = *(unsigned char*)cp++; #endif } } if(c==0 || c=='#' || c=='~') state = 1; #if SHOPT_MULTIBYTE for(;c;c= mbchar(cp)) #else for(;c; c= *(unsigned char*)cp++) #endif { #if SHOPT_MULTIBYTE if(c=='\'' || !iswprint(c)) #else if(c=='\'' || !isprint(c)) #endif /* SHOPT_MULTIBYTE */ state = 2; else if(c==']' || (c!=':' && c<=0xff && (c=sh_lexstates[ST_NORM][c]) && c!=S_EPAT)) state |=1; } if(state<2) { if(state==1) stakputc('\''); if(c = --cp - string) stakwrite(string,c); if(state==1) stakputc('\''); } else { stakwrite("$'",2); cp = string; #if SHOPT_MULTIBYTE while(op = cp, c= mbchar(cp)) #else while(op = cp, c= *(unsigned char*)cp++) #endif { state=1; switch(c) { case ('a'==97?'\033':39): c = 'E'; break; case '\n': c = 'n'; break; case '\r': c = 'r'; break; case '\t': c = 't'; break; case '\f': c = 'f'; break; case '\b': c = 'b'; break; case '\a': c = 'a'; break; case '\\': case '\'': break; default: #if SHOPT_MULTIBYTE if(!iswprint(c)) { while(op<cp) sfprintf(staksp,"\\%.3o",*(unsigned char*)op++); continue; } #else if(!isprint(c)) { sfprintf(staksp,"\\%.3o",c); continue; } #endif state=0; break; } if(state) { stakputc('\\'); stakputc(c); } else stakwrite(op, cp-op); } stakputc('\''); } stakputc(0); return(stakptr(offset)); }