static_fn void p_arg(const struct argnod *arg, int endchar, int opts) { int flag = -1; do { if (!arg->argnxt.ap) { flag = endchar; } else if (opts & PRE) { // case alternation lists in reverse order p_arg(arg->argnxt.ap, '|', opts); flag = endchar; } else if (opts) { flag = ' '; } const char *cp = arg->argval; if (*cp == 0 && (arg->argflag & ARG_EXP) && arg->argchn.ap) { int c = (arg->argflag & ARG_RAW) ? '>' : '<'; sfputc(outfile, c); sfputc(outfile, '('); p_tree((Shnode_t *)arg->argchn.ap, 0); sfputc(outfile, ')'); } else if (*cp == 0 && opts == POST && arg->argchn.ap) { // compound assignment struct fornod *fp = (struct fornod *)arg->argchn.ap; sfprintf(outfile, "%s=(\n", fp->fornam); sfnputc(outfile, '\t', ++level); p_tree(fp->fortre, 0); if (--level) sfnputc(outfile, '\t', level); sfputc(outfile, ')'); } else if ((arg->argflag & ARG_RAW) && (cp[1] || (*cp != '[' && *cp != ']'))) { cp = sh_fmtq(cp); } sfputr(outfile, cp, flag); if (flag == '\n') begin_line = 1; arg = arg->argnxt.ap; } while ((opts & POST) && arg); }
static int paste(int nstream,Sfio_t* streams[],Sfio_t *out, register const char *delim, int dsiz, int dlen, Delim_t* mp) { register const char *cp; register int d, n, i, z, more=1; register Sfio_t *fp; do { d = (dlen>0?0:-1); for(n=more-1,more=0; n < nstream;) { if(fp=streams[n]) { if(cp = sfgetr(fp,'\n',0)) { if(n==0) more = 1; else if(!more) /* first stream with output */ { if(dsiz == 1) sfnputc(out, *delim, n); else if(dlen>0) { for(d=n; d>dlen; d-=dlen) sfwrite(out,delim,dsiz); if(d) { if(mp) for (i = z = 0; i < d; i++) z += mp[i].len; else z = d; sfwrite(out,delim,z); } } more = n+1; } if(sfwrite(out,cp,sfvalue(fp)-((n+1)<nstream)) < 0) return(-1); } else streams[n] = 0; } if(++n<nstream && more && d>=0) { register int c; if(d >= dlen) d = 0; if(mp) sfwrite(out,mp[d].chr,mp[d].len); else if(c=delim[d]) sfputc(out,c); d++; } else if(n==nstream && !streams[n-1] && more) sfputc(out,'\n'); } } while(more); return(0); }
static void p_arg(register const struct argnod *arg,register int endchar,int opts) { register const char *cp; register int flag; do { if(!arg->argnxt.ap) flag = endchar; else if(opts&PRE) { /* case alternation lists in reverse order */ p_arg(arg->argnxt.ap,'|',opts); flag = endchar; } else if(opts) flag = ' '; cp = arg->argval; if(*cp==0 && opts==POST && arg->argchn.ap) { /* compound assignment */ struct fornod *fp=(struct fornod*)arg->argchn.ap; sfprintf(outfile,"%s=(\n",fp->fornam); sfnputc(outfile,'\t',++level); p_tree(fp->fortre,0); if(--level) sfnputc(outfile,'\t',level); sfputc(outfile,')'); } else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']'))) cp = sh_fmtq(cp); sfputr(outfile,cp,flag); if(flag=='\n') begin_line = 1; arg = arg->argnxt.ap; } while((opts&POST) && arg); return; }
static_fn void p_switch(const struct regnod *reg) { if (level > 1) sfnputc(outfile, '\t', level - 1); p_arg(reg->regptr, ')', PRE); begin_line = 0; sfputc(outfile, '\t'); if (reg->regcom) p_tree(reg->regcom, 0); level++; if (reg->regflag) { p_keyword(";&", END); } else { p_keyword(";;", END); } if (reg->regnxt) p_switch(reg->regnxt); }
// Print a keyword. // Increment indent level for flag==BEGIN. // Decrement indent level for flag==END. static_fn void p_keyword(const char *word, int flag) { int sep; if (flag == END) { sep = end_line; } else if (*word == '[' || *word == '(') { sep = ' '; } else { sep = '\t'; } if (flag != BEGIN) level--; if (begin_line && level) sfnputc(outfile, '\t', level); sfputr(outfile, word, sep); if (sep == '\n') { begin_line = 1; } else { begin_line = 0; } if (flag != END) level++; }
/* * print a keyword * increment indent level for flag==BEGIN * decrement indent level for flag==END */ static void p_keyword(const char *word,int flag) { register int sep; if(flag==END) sep = end_line; else if(*word=='[' || *word=='(') sep = ' '; else sep = '\t'; if(flag!=BEGIN) level--; if(begin_line && level) sfnputc(outfile,'\t',level); sfputr(outfile,word,sep); if(sep=='\n') begin_line=1; else begin_line=0; if(flag!=END) level++; }
static void banner(const char *string,const char *delim,int width) { register unsigned mask; register int c,i,n,j = strlen(string); register const char *cp,*dp; register unsigned char* map; map = ccmap(CC_NATIVE, CC_ASCII); if(j > width/8) error(ERROR_exit(1),"up to %d char%s per arg",width/8,(width/8)==1?"":"s"); for(i=0; i < CHAR_HEIGHT; i++) { dp = delim; for (n = 0, cp = string; c = ccmapchr(map, *cp++) & 0x07f; dp++) { if(*dp==0) dp = delim; if((mask = bandata[c][i])==0) { n += 8; continue; } for(j=0x80; j>0; j >>=1) { if(mask&j) { if(n) { sfnputc(sfstdout,' ',n); n = 0; } sfputc(sfstdout,*dp); } else n++; } } sfputc(sfstdout,'\n'); } }
// Print script corresponding to shell tree <t>. static_fn void p_tree(const Shnode_t *t, int tflags) { char *cp = NULL; int save = end_line; int needbrace = (tflags & NEED_BRACE); int bracket = 0; tflags &= ~NEED_BRACE; if (tflags & NO_NEWLINE) { end_line = ' '; } else { end_line = '\n'; } int cmd_type = t->tre.tretyp & COMMSK; switch (cmd_type) { case TTIME: { if (t->tre.tretyp & COMSCAN) { p_keyword("!", BEGIN); } else { p_keyword("time", BEGIN); } if (t->par.partre) p_tree(t->par.partre, tflags); level--; break; } case TCOM: { if (begin_line && level > 0) sfnputc(outfile, '\t', level); begin_line = 0; p_comarg((struct comnod *)t); break; } case TSETIO: { if (t->tre.tretyp & FPCL) { tflags |= NEED_BRACE; } else { tflags = NO_NEWLINE | NEED_BRACE; } p_tree(t->fork.forktre, tflags); p_redirect(t->fork.forkio); break; } case TFORK: { if (needbrace) tflags |= NEED_BRACE; if (t->tre.tretyp & (FAMP | FCOOP)) { tflags = NEED_BRACE | NO_NEWLINE; end_line = ' '; } else if (t->fork.forkio) { tflags = NO_NEWLINE; } p_tree(t->fork.forktre, tflags); if (t->fork.forkio) p_redirect(t->fork.forkio); if (t->tre.tretyp & FCOOP) { sfputr(outfile, "|&", '\n'); begin_line = 1; } else if (t->tre.tretyp & FAMP) { sfputr(outfile, "&", '\n'); begin_line = 1; } break; } case TIF: { p_keyword("if", BEGIN); p_tree(t->if_.iftre, 0); p_keyword("then", MIDDLE); p_tree(t->if_.thtre, 0); if (t->if_.eltre) { p_keyword("else", MIDDLE); p_tree(t->if_.eltre, 0); } p_keyword("fi", END); break; } case TWH: { if (t->wh.whinc) { cp = "for"; } else if (t->tre.tretyp & COMSCAN) { cp = "until"; } else { cp = "while"; } p_keyword(cp, BEGIN); if (t->wh.whinc) { struct argnod *arg = (t->wh.whtre)->ar.arexpr; sfprintf(outfile, "(( %s; ", forinit); forinit = ""; sfputr(outfile, arg->argval, ';'); arg = (t->wh.whinc)->arexpr; sfprintf(outfile, " %s))\n", arg->argval); } else { p_tree(t->wh.whtre, 0); } t = t->wh.dotre; p_keyword("do", MIDDLE); p_tree(t, 0); p_keyword("done", END); break; } case TLST: { Shnode_t *tr = t->lst.lstrit; if (tr->tre.tretyp == TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp == TARITH) { // Arithmetic for statement. struct argnod *init = (t->lst.lstlef)->ar.arexpr; forinit = init->argval; p_tree(t->lst.lstrit, tflags); break; } if (needbrace) p_keyword("{", BEGIN); p_tree(t->lst.lstlef, 0); if (needbrace) tflags = 0; p_tree(t->lst.lstrit, tflags); if (needbrace) p_keyword("}", END); break; } case TAND: case TORF: case TFIL: { if (cmd_type == TAND) { cp = "&&"; } else if (cmd_type == TORF) { cp = "||"; } else { cp = "|"; } if (t->tre.tretyp & TTEST) { tflags |= NO_NEWLINE; if (!(tflags & NO_BRACKET)) { p_keyword("[[", BEGIN); tflags |= NO_BRACKET; bracket = 1; } } p_tree(t->lst.lstlef, NEED_BRACE | NO_NEWLINE | (tflags & NO_BRACKET)); if (tflags & FALTPIPE) { Shnode_t *tt = t->lst.lstrit; if (tt->tre.tretyp != TFIL || !(tt->lst.lstlef->tre.tretyp & FALTPIPE)) { sfputc(outfile, '\n'); return; } } sfputr(outfile, cp, here_doc ? '\n' : ' '); if (here_doc) { here_body(here_doc); here_doc = 0; } level++; p_tree(t->lst.lstrit, tflags | NEED_BRACE); if (bracket) p_keyword("]]", END); level--; break; } case TPAR: { p_keyword("(", BEGIN); p_tree(t->par.partre, 0); p_keyword(")", END); break; } case TARITH: { struct argnod *ap = t->ar.arexpr; if (begin_line && level) sfnputc(outfile, '\t', level); sfprintf(outfile, "(( %s ))%c", ap->argval, end_line); if (!(tflags & NO_NEWLINE)) begin_line = 1; break; } case TFOR: { cp = ((t->tre.tretyp & COMSCAN) ? "select" : "for"); p_keyword(cp, BEGIN); sfputr(outfile, t->for_.fornam, ' '); if (t->for_.forlst) { sfputr(outfile, "in", ' '); tflags = end_line; end_line = '\n'; p_comarg(t->for_.forlst); end_line = tflags; } else { sfputc(outfile, '\n'); } begin_line = 1; t = t->for_.fortre; p_keyword("do", MIDDLE); p_tree(t, 0); p_keyword("done", END); break; } case TSW: { p_keyword("case", BEGIN); p_arg(t->sw.swarg, ' ', 0); if (t->sw.swlst) { begin_line = 1; sfputr(outfile, "in", '\n'); tflags = end_line; end_line = '\n'; p_switch(t->sw.swlst); end_line = tflags; } p_keyword("esac", END); break; } case TFUN: { if (t->tre.tretyp & FPOSIX) { sfprintf(outfile, "%s", t->funct.functnam); p_keyword("()\n", BEGIN); } else { p_keyword("function", BEGIN); tflags = (t->funct.functargs ? ' ' : '\n'); sfputr(outfile, t->funct.functnam, tflags); if (t->funct.functargs) { tflags = end_line; end_line = '\n'; p_comarg(t->funct.functargs); end_line = tflags; } } begin_line = 1; p_keyword("{\n", MIDDLE); begin_line = 1; p_tree(t->funct.functtre, 0); p_keyword("}", END); break; } case TTST: { // new test compound command if (!(tflags & NO_BRACKET)) p_keyword("[[", BEGIN); if ((t->tre.tretyp & TPAREN) == TPAREN) { p_keyword("(", BEGIN); p_tree(t->lst.lstlef, NO_BRACKET | NO_NEWLINE); p_keyword(")", END); } else { int flags = (t->tre.tretyp) >> TSHIFT; if (t->tre.tretyp & TNEGATE) sfputr(outfile, "!", ' '); if (t->tre.tretyp & TUNARY) { un_op[1] = flags; sfputr(outfile, un_op, ' '); } else { cp = ((char *)(shtab_testops + (flags & 037) - 1)->sh_name); } p_arg(&(t->lst.lstlef->arg), ' ', 0); if (t->tre.tretyp & TBINARY) { assert(cp); sfputr(outfile, cp, ' '); p_arg(&(t->lst.lstrit->arg), ' ', 0); } } if (!(tflags & NO_BRACKET)) p_keyword("]]", END); } default: { break; } } while (begin_line && here_doc) { here_body(here_doc); here_doc = 0; } end_line = save; }
// Print option settings on standard output. // If mode is inclusive or of PRINT_*. // If <mask> is set, only options with this mask value are displayed. void sh_printopts(Shell_t *shp, Shopt_t oflags, int mode, Shopt_t *mask) { const Shtable_t *tp; const char *name; int on; int value; if (!(mode & PRINT_NO_HEADER)) sfputr(sfstdout, sh_translate(e_heading), '\n'); if (mode & PRINT_TABLE) { size_t w; int c; int r; int i; c = 0; for (tp = shtab_options; (value = tp->sh_number); tp++) { if (mask && !is_option(mask, value & 0xff)) continue; name = tp->sh_name; if (name[0] == 'n' && name[1] == 'o' && name[2] != 't') name += 2; if (c < (w = strlen(name))) c = w; } c += 4; w = ed_window(); if (w < 2 * c) w = 2 * c; r = w / c; i = 0; for (tp = shtab_options; (value = tp->sh_number); tp++) { if (mask && !is_option(mask, value & 0xff)) continue; on = is_option(&oflags, value); name = tp->sh_name; if (name[0] == 'n' && name[1] == 'o' && name[2] != 't') { name += 2; on = !on; } if (++i >= r) { i = 0; sfprintf(sfstdout, "%s%s\n", on ? "" : "no", name); } else { sfprintf(sfstdout, "%s%-*s", on ? "" : "no", on ? c : (c - 2), name); } } if (i) sfputc(sfstdout, '\n'); return; } if (!(mode & (PRINT_ALL | PRINT_VERBOSE))) { // only print set options if (mode & PRINT_SHOPT) { sfwrite(sfstdout, "shopt -s", 3); } else { sfwrite(sfstdout, "set --default", 13); } } for (tp = shtab_options; (value = tp->sh_number); tp++) { if (mask && !is_option(mask, value & 0xff)) continue; if (sh_isoption(shp, SH_BASH)) { if (!(mode & PRINT_SHOPT) != !(value & SH_BASHOPT)) continue; } else if (value & (SH_BASHEXTRA | SH_BASHOPT)) { continue; } on = is_option(&oflags, value); name = tp->sh_name; if (name[0] == 'n' && name[1] == 'o' && name[2] != 't') { name += 2; on = !on; } if (mode & PRINT_VERBOSE) { sfputr(sfstdout, name, ' '); sfnputc(sfstdout, ' ', 24 - strlen(name)); sfputr(sfstdout, on ? sh_translate(e_on) : sh_translate(e_off), '\n'); } else if (mode & PRINT_ALL) { // print unset options also if (mode & PRINT_SHOPT) { sfprintf(sfstdout, "shopt -%c %s\n", on ? 's' : 'u', name); } else { sfprintf(sfstdout, "set %co %s\n", on ? '-' : '+', name); } } else if (!(value & SH_COMMANDLINE) && is_option(&oflags, value & 0xff)) { sfprintf(sfstdout, " %s%s%s", (mode & PRINT_SHOPT) ? "" : "--", on ? "" : "no", name); } } if (!(mode & (PRINT_VERBOSE | PRINT_ALL))) sfputc(sfstdout, '\n'); }
static void genvalue(Sfio_t *out, Shclass_t *sp, int indent, Namval_t *npar) { Shfield_t *fp = sp->fields; Namval_t *np, **nodes= (Namval_t**)(sp+1); register int i,isarray; if(out) { sfwrite(out,"(\n",2); indent++; } for(i=0; i < sp->nelem; i++,fp++) { #if 0 /* handle recursive case */ #endif if(!(np=nodes[i]) && out) np = sh_newnode(fp,npar); if(np) { isarray=0; if(nv_isattr(np,NV_ARRAY)) { isarray=1; if(array_elem(nv_arrayptr(np))==0) isarray=2; else nv_putsub(np,(char*)0,ARRAY_SCAN); } sfnputc(out,'\t',indent); sfputr(out,fp->name,(isarray==2?'\n':'=')); if(isarray) { if(isarray==2) continue; sfwrite(out,"(\n",2); sfnputc(out,'\t',++indent); } while(1) { char *fmtq; if(isarray) { sfprintf(out,"[%s]",sh_fmtq(nv_getsub(np))); sfputc(out,'='); } if(!(fmtq=nv_getval(np)) || !(fmtq=sh_fmtq(fmtq))) fmtq = ""; sfputr(out,fmtq,'\n'); if(!nv_nextsub(np)) break; sfnputc(out,'\t',indent); } if(isarray) { sfnputc(out,'\t',--indent); sfwrite(out,")\n",2); } } } if(out) { if(indent>1) sfnputc(out,'\t',indent-1); sfputc(out,')'); } }
tmain() { UNUSED(argc); UNUSED(argv); Sfio_t *f, *f2; char *s; int i, n; char buf[16 * 1024]; if (!(f = sfopen(NULL, tstfile("sf", 0), "w+"))) terror("Can't open file"); if (sfnputc(f, 'a', 1000) != 1000) terror("Writing"); if (sfseek(f, (Sfoff_t)0, 0) != 0) terror("Seeking"); if ((n = (int)sfsize(f)) != 1000) terror("Wrong size %d", n); if (!(f2 = sfnew(NULL, NULL, (size_t)SF_UNBOUND, sffileno(f), SF_WRITE))) { terror("Can't open stream"); } if (sfseek(f2, (Sfoff_t)1999, 0) != (Sfoff_t)1999) terror("Seeking2"); sfputc(f2, 'b'); sfsync(f2); if ((n = (int)sfsize(f2)) != 2000) terror("Wrong size2 %d", n); if ((n = (int)sfsize(f)) != 1000) terror("Wrong size3 %d", n); sfputc(f, 'a'); sfset(f, SF_SHARE, 1); if ((n = (int)sfsize(f)) != 2000) terror("Wrong size4 %d", n); if (!(f = sfopen(f, NULL, "srw"))) terror("Can't open string stream"); sfwrite(f, "0123456789", 10); if (sfsize(f) != 10) terror("String size is wrong1"); sfseek(f, (Sfoff_t)19, 0); if (sfsize(f) != 10) terror("String size is wrong2"); sfputc(f, 'a'); if (sfsize(f) != 20) terror("String size is wrong3"); sfseek(f, (Sfoff_t)0, 0); if (sfsize(f) != 20) terror("String size is wrong4"); sfseek(f, (Sfoff_t)0, 0); if (!(s = sfreserve(f, SF_UNBOUND, SF_LOCKR)) && sfvalue(f) != 20) { terror("String size is wrong5"); } sfread(f, s, 5); if (sfsize(f) != 20) terror("String size is wrong6"); sfwrite(f, "01234567890123456789", 20); if (sfsize(f) != 25) terror("String size is wrong7"); strcpy(buf, "0123456789"); if (!(f = sfopen(f, buf, "s+"))) terror("Can't open string stream2"); if (sfset(f, 0, 0) & SF_MALLOC) terror("SF_MALLOC should not have been set"); if (sfsize(f) != 10) terror("String size is wrong8"); sfread(f, buf, 5); if ((n = (int)sfwrite(f, "0123456789", 10)) != 5) terror("Write wrong amount %d", n); if (sfsize(f) != 10) terror("String size is wrong9"); if (!(f = sfopen(f, tstfile("sf", 0), "w"))) terror("Reopening file1"); for (i = 0; i < 10000; ++i) { if (sfputc(f, '0' + (i % 10)) != '0' + (i % 10)) terror("sfputc failed"); } if (!(f = sfopen(f, tstfile("sf", 0), "r+"))) terror("Reopening file2"); if (sfsize(f) != 10000) terror("Bad size of file1"); sfsetbuf(f, buf, 1024); for (i = 0; i < 20; ++i) { if (!sfreserve(f, 100, 0)) terror("Reserve failed"); } s = buf + 1024; for (i = 0; i < 20; ++i) s[i] = '0' + i % 10; sfseek(f, (Sfoff_t)(10000 - 10), 0); if (sfwrite(f, s, 20) != 20) terror("Write failed"); if (sfsize(f) != 10010) terror("Bad size of file2"); sfseek(f, (Sfoff_t)0, 0); for (i = 0; i < 10; ++i) { if (!(s = sfreserve(f, 1001, 0))) terror("Reserve failed2"); if (s[0] != '0' + i) terror("Bad data1"); } for (n = 0; n < 1001; ++n) { if (s[n] != ((n + i - 1) % 10 + '0')) terror("Bad data"); } /* test to see if a string stream extends ok during writes */ s = malloc(5); f = sfnew(NULL, (void *)s, 5, -1, SF_STRING | SF_READ | SF_WRITE | SF_MALLOC); if (!f) terror("Can't create string stream"); if (sfwrite(f, "01", 2) != 2) terror("Bad write to string stream"); if (sfwrite(f, "2345678", 7) != 7) terror("Bad write to string stream2"); if (sfputc(f, 0) != 0) terror("sfputc failed"); if (sfseek(f, (Sfoff_t)0, 0) != 0) terror("sfseek failed"); if ((n = (int)sfread(f, buf, 100)) != 10) terror("sfread gets wrong amount of data %d", n); if (strcmp(buf, "012345678") != 0) terror("Get wrong data"); texit(0); }