summaryrefslogtreecommitdiff
path: root/usr/src/lib/libshell/common/sh/tdump.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libshell/common/sh/tdump.c')
-rw-r--r--usr/src/lib/libshell/common/sh/tdump.c260
1 files changed, 260 insertions, 0 deletions
diff --git a/usr/src/lib/libshell/common/sh/tdump.c b/usr/src/lib/libshell/common/sh/tdump.c
new file mode 100644
index 0000000000..80ef55a9aa
--- /dev/null
+++ b/usr/src/lib/libshell/common/sh/tdump.c
@@ -0,0 +1,260 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1982-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * David Korn
+ * AT&T Labs
+ *
+ * shell parse tree dump
+ *
+ */
+
+#include <ccode.h>
+#include "defs.h"
+#include "shnodes.h"
+#include "path.h"
+#include "io.h"
+
+static int p_comlist(const struct dolnod*);
+static int p_arg(const struct argnod*);
+static int p_comarg(const struct comnod*);
+static int p_redirect(const struct ionod*);
+static int p_switch(const struct regnod*);
+static int p_tree(const Shnode_t*);
+static int p_string(const char*);
+
+static Sfio_t *outfile;
+
+int sh_tdump(Sfio_t *out, const Shnode_t *t)
+{
+ outfile = out;
+ return(p_tree(t));
+}
+
+/*
+ * convert to ASCII to write and back again if needed
+ */
+static int outstring(Sfio_t *out, const char *string, int n)
+{
+ int r;
+ char *cp = (char*)string;
+ ccmaps(cp, n, CC_NATIVE, CC_ASCII);
+ r = sfwrite(out,cp,n);
+ ccmaps(cp, n, CC_ASCII, CC_NATIVE);
+ return(r);
+}
+
+/*
+ * print script corresponding to shell tree <t>
+ */
+static int p_tree(register const Shnode_t *t)
+{
+ if(!t)
+ return(sfputl(outfile,-1));
+ if(sfputl(outfile,t->tre.tretyp)<0)
+ return(-1);
+ switch(t->tre.tretyp&COMMSK)
+ {
+ case TTIME:
+ case TPAR:
+ return(p_tree(t->par.partre));
+ case TCOM:
+ return(p_comarg((struct comnod*)t));
+ case TSETIO:
+ case TFORK:
+ if(sfputu(outfile,t->fork.forkline)<0)
+ return(-1);
+ if(p_tree(t->fork.forktre)<0)
+ return(-1);
+ return(p_redirect(t->fork.forkio));
+ case TIF:
+ if(p_tree(t->if_.iftre)<0)
+ return(-1);
+ if(p_tree(t->if_.thtre)<0)
+ return(-1);
+ return(p_tree(t->if_.eltre));
+ case TWH:
+ if(t->wh.whinc)
+ {
+ if(p_tree((Shnode_t*)(t->wh.whinc))<0)
+ return(-1);
+ }
+ else
+ {
+ if(sfputl(outfile,-1)<0)
+ return(-1);
+ }
+ if(p_tree(t->wh.whtre)<0)
+ return(-1);
+ return(p_tree(t->wh.dotre));
+ case TLST:
+ case TAND:
+ case TORF:
+ case TFIL:
+ if(p_tree(t->lst.lstlef)<0)
+ return(-1);
+ return(p_tree(t->lst.lstrit));
+ case TARITH:
+ if(sfputu(outfile,t->ar.arline)<0)
+ return(-1);
+ return(p_arg(t->ar.arexpr));
+ case TFOR:
+ if(sfputu(outfile,t->for_.forline)<0)
+ return(-1);
+ if(p_tree(t->for_.fortre)<0)
+ return(-1);
+ if(p_string(t->for_.fornam)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->for_.forlst));
+ case TSW:
+ if(sfputu(outfile,t->sw.swline)<0)
+ return(-1);
+ if(p_arg(t->sw.swarg)<0)
+ return(-1);
+ return(p_switch(t->sw.swlst));
+ case TFUN:
+ if(sfputu(outfile,t->funct.functline)<0)
+ return(-1);
+ if(p_string(t->funct.functnam)<0)
+ return(-1);
+ if(p_tree(t->funct.functtre)<0)
+ return(-1);
+ return(p_tree((Shnode_t*)t->funct.functargs));
+ case TTST:
+ if(sfputu(outfile,t->tst.tstline)<0)
+ return(-1);
+ if((t->tre.tretyp&TPAREN)==TPAREN)
+ return(p_tree(t->lst.lstlef));
+ else
+ {
+ if(p_arg(&(t->lst.lstlef->arg))<0)
+ return(-1);
+ if((t->tre.tretyp&TBINARY))
+ return(p_arg(&(t->lst.lstrit->arg)));
+ return(0);
+ }
+ }
+ return(-1);
+}
+
+static int p_arg(register const struct argnod *arg)
+{
+ register int n;
+ struct fornod *fp;
+ while(arg)
+ {
+ if((n = strlen(arg->argval)) || (arg->argflag&~ARG_APPEND))
+ fp=0;
+ else
+ {
+ fp=(struct fornod*)arg->argchn.ap;
+ n = strlen(fp->fornam)+1;
+ }
+ sfputu(outfile,n+1);
+ if(fp)
+ {
+ sfputc(outfile,0);
+ outstring(outfile,fp->fornam,n-1);
+ }
+ else
+ outstring(outfile,arg->argval,n);
+ sfputc(outfile,arg->argflag);
+ if(fp)
+ {
+ sfputu(outfile,fp->fortyp);
+ p_tree(fp->fortre);
+ }
+ arg = arg->argnxt.ap;
+ }
+ return(sfputu(outfile,0));
+}
+
+static int p_redirect(register const struct ionod *iop)
+{
+ while(iop)
+ {
+ if(iop->iovname)
+ sfputl(outfile,iop->iofile|IOVNM);
+ else
+ sfputl(outfile,iop->iofile);
+ p_string(iop->ioname);
+ if(iop->iodelim)
+ {
+ p_string(iop->iodelim);
+ sfputl(outfile,iop->iosize);
+ sfseek(sh.heredocs,iop->iooffset,SEEK_SET);
+ sfmove(sh.heredocs,outfile, iop->iosize,-1);
+ }
+ else
+ sfputu(outfile,0);
+ if(iop->iovname)
+ p_string(iop->iovname);
+ iop = iop->ionxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_comarg(register const struct comnod *com)
+{
+ p_redirect(com->comio);
+ p_arg(com->comset);
+ if(!com->comarg)
+ sfputl(outfile,-1);
+ else if(com->comtyp&COMSCAN)
+ p_arg(com->comarg);
+ else
+ p_comlist((struct dolnod*)com->comarg);
+ return(sfputu(outfile,com->comline));
+}
+
+static int p_comlist(const struct dolnod *dol)
+{
+ register char *cp, *const*argv;
+ register int n;
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv)
+ argv++;
+ n = argv - (dol->dolval+1);
+ sfputl(outfile,n);
+ argv = dol->dolval+ARG_SPARE;
+ while(cp = *argv++)
+ p_string(cp);
+ return(sfputu(outfile,0));
+}
+
+static int p_switch(register const struct regnod *reg)
+{
+ while(reg)
+ {
+ sfputl(outfile,reg->regflag);
+ p_arg(reg->regptr);
+ p_tree(reg->regcom);
+ reg = reg->regnxt;
+ }
+ return(sfputl(outfile,-1));
+}
+
+static int p_string(register const char *string)
+{
+ register size_t n=strlen(string);
+ if(sfputu(outfile,n+1)<0)
+ return(-1);
+ return(outstring(outfile,string,n));
+}