Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtksh / ksh93 / src / cmd / ksh93 / sh / deparse.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: deparse.c /main/3 1996/05/08 19:39:37 drk $ */
24 /***************************************************************
25 *                                                              *
26 *                      AT&T - PROPRIETARY                      *
27 *                                                              *
28 *        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF        *
29 *                    AT&T BELL LABORATORIES                    *
30 *         AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN         *
31 *            ACCORDANCE WITH APPLICABLE AGREEMENTS             *
32 *                                                              *
33 *                Copyright (c) 1995 AT&T Corp.                 *
34 *              Unpublished & Not for Publication               *
35 *                     All Rights Reserved                      *
36 *                                                              *
37 *       The copyright notice above does not evidence any       *
38 *      actual or intended publication of such source code      *
39 *                                                              *
40 *               This software was created by the               *
41 *           Advanced Software Technology Department            *
42 *                    AT&T Bell Laboratories                    *
43 *                                                              *
44 *               For further information contact                *
45 *                    {research,attmail}!dgk                    *
46 *                                                              *
47 ***************************************************************/
48
49 /* : : generated by proto : : */
50
51 #if !defined(__PROTO__)
52 #if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)
53 #if defined(__cplusplus)
54 #define __MANGLE__      "C"
55 #else
56 #define __MANGLE__
57 #endif
58 #define __STDARG__
59 #define __PROTO__(x)    x
60 #define __OTORP__(x)
61 #define __PARAM__(n,o)  n
62 #if !defined(__STDC__) && !defined(__cplusplus)
63 #if !defined(c_plusplus)
64 #define const
65 #endif
66 #define signed
67 #define void            int
68 #define volatile
69 #define __V_            char
70 #else
71 #define __V_            void
72 #endif
73 #else
74 #define __PROTO__(x)    ()
75 #define __OTORP__(x)    x
76 #define __PARAM__(n,o)  o
77 #define __MANGLE__
78 #define __V_            char
79 #define const
80 #define signed
81 #define void            int
82 #define volatile
83 #endif
84 #if defined(__cplusplus) || defined(c_plusplus)
85 #define __VARARG__      ...
86 #else
87 #define __VARARG__
88 #endif
89 #if defined(__STDARG__)
90 #define __VA_START__(p,a)       va_start(p,a)
91 #else
92 #define __VA_START__(p,a)       va_start(p)
93 #endif
94 #endif
95 #include        "defs.h"
96 #include        "shnodes.h"
97 #include        "test.h"
98
99
100 #define HUGE_INT        (((unsigned)-1)>>1)
101 #define BEGIN   0
102 #define MIDDLE  1
103 #define END     2
104 #define PRE     1
105 #define POST    2
106
107
108 /* flags that can be specified with p_tree() */
109 #define NO_NEWLINE      1
110 #define NEED_BRACE      2
111
112 static void p_comlist __PROTO__((const struct dolnod*,int));
113 static void p_arg __PROTO__((const struct argnod*, int endchar, int opts));
114 static void p_comarg __PROTO__((const struct comnod*));
115 static void p_keyword __PROTO__((const char*,int));
116 static void p_redirect __PROTO__((const struct ionod*));
117 static void p_switch __PROTO__((const struct regnod*));
118 static void here_body __PROTO__((const struct ionod*));
119 static void p_tree __PROTO__((const union anynode*,int));
120
121 static int level;
122 static int begin_line;
123 static int end_line;
124 static char io_op[5];
125 static char un_op[3] = "-?";
126 static const struct ionod *here_doc;
127 static Sfio_t *outfile;
128 static const char *forinit = "";
129
130 extern __MANGLE__ void sh_deparse __PROTO__((Sfio_t*, const union anynode*,int));
131
132 void sh_deparse __PARAM__((Sfio_t *out, const union anynode *t,int tflags), (out, t, tflags)) __OTORP__(Sfio_t *out; const union anynode *t;int tflags;){
133         outfile = out;
134         p_tree(t,tflags);
135 }
136 /*
137  * print script corresponding to shell tree <t>
138  */
139 static void p_tree __PARAM__((register const union anynode *t,register int tflags), (t, tflags)) __OTORP__(register const union anynode *t;register int tflags;){
140         register char *cp;
141         int save = end_line;
142         int needbrace = (tflags&NEED_BRACE);
143         tflags &= ~NEED_BRACE;
144         if(tflags&NO_NEWLINE)
145                 end_line = ' ';
146         else
147                 end_line = '\n';
148         switch(t->tre.tretyp&COMMSK)
149         {
150                 case TTIME:
151                         if(t->tre.tretyp&COMSCAN)
152                                 p_keyword("!",BEGIN);
153                         else
154                                 p_keyword("time",BEGIN);
155                         if(t->par.partre)
156                                 p_tree(t->par.partre,tflags); 
157                         level--;
158                         break;
159
160                 case TCOM:
161                         if(begin_line && level>0)
162                                 sfnputc(outfile,'\t',level);
163                         begin_line = 0;
164                         p_comarg((struct comnod*)t);
165                         break;
166
167                 case TSETIO:
168                         if(t->tre.tretyp&FPCL)
169                                 tflags = NEED_BRACE;
170                         else
171                                 tflags = NO_NEWLINE|NEED_BRACE;
172                         p_tree(t->fork.forktre,tflags);
173                         p_redirect(t->fork.forkio);
174                         break;
175
176                 case TFORK:
177                         if(needbrace)
178                                 tflags |= NEED_BRACE;
179                         if(t->tre.tretyp&(FAMP|FCOOP))
180                         {
181                                 tflags = NEED_BRACE|NO_NEWLINE;
182                                 end_line = ' ';
183                         }
184                         else if(t->fork.forkio)
185                                 tflags = NO_NEWLINE;
186                         p_tree(t->fork.forktre,tflags);
187                         if(t->fork.forkio)
188                                 p_redirect(t->fork.forkio);
189                         if(t->tre.tretyp&FCOOP)
190                         {
191                                 sfputr(outfile,"|&",'\n');
192                                 begin_line = 1;
193                         }
194                         else if(t->tre.tretyp&FAMP)
195                         {
196                                 sfputr(outfile,"&",'\n');
197                                 begin_line = 1;
198                         }
199                         break;
200         
201                 case TIF:
202                         p_keyword("if",BEGIN);
203                         p_tree(t->if_.iftre,0);
204                         p_keyword("then",MIDDLE);
205                         p_tree(t->if_.thtre,0);
206                         if(t->if_.eltre)
207                         {
208                                 p_keyword("else",MIDDLE);
209                                 p_tree(t->if_.eltre,0);
210                         }
211                         p_keyword("fi",END);
212                         break;
213
214                 case TWH:
215                         if(t->wh.whinc)
216                                 cp = "for";
217                         else if(t->tre.tretyp&COMSCAN)
218                                 cp = "until";
219                         else
220                                 cp = "while";
221                         p_keyword(cp,BEGIN);
222                         if(t->wh.whinc)
223                         {
224                                 struct argnod *arg = (t->wh.whtre)->ar.arexpr;
225                                 struct argnod *incr = (t->wh.whinc)->arexpr;
226                                 sfprintf(outfile,"(( %s; ",forinit);
227                                 forinit = "";
228                                 sfputr(outfile,arg->argflag&ARG_RAW?sh_fmtq(arg->argval):arg->argval,';');
229                                 arg = (t->wh.whinc)->arexpr;
230                                 sfprintf(outfile," %s))\n",arg->argflag&ARG_RAW?sh_fmtq(arg->argval):arg->argval);
231                         }
232                         else
233                                 p_tree(t->wh.whtre,0);
234                         t = t->wh.dotre;
235                         goto dolist;
236
237                 case TLST:
238                 {
239                         union anynode *tr = t->lst.lstrit;
240                         if(tr->tre.tretyp==TWH && tr->wh.whinc && t->lst.lstlef->tre.tretyp==TARITH)
241                         {
242                                 /* arithmetic for statement */
243                                 struct argnod *init = (t->lst.lstlef)->ar.arexpr;
244                                 forinit= (init->argflag&ARG_RAW)?sh_fmtq(init->argval):tr->arg.argval;
245                                 p_tree(t->lst.lstrit,tflags);
246                                 break;
247                         }
248                         if(needbrace)
249                                 p_keyword("{",BEGIN);
250                         p_tree(t->lst.lstlef,0);
251                         if(needbrace)
252                                 tflags = 0;
253                         p_tree(t->lst.lstrit,tflags);
254                         if(needbrace)
255                                 p_keyword("}",END);
256                         break;
257                 }
258
259                 case TAND:
260                         cp = "&&";
261                         goto andor;
262                 case TORF:
263                         cp = "||";
264                         goto andor;
265                 case TFIL:
266                         cp = "|";
267                 andor:
268                         p_tree(t->lst.lstlef,NEED_BRACE|NO_NEWLINE);
269                         sfputr(outfile,cp,' ');
270                         level++;
271                         p_tree(t->lst.lstrit,tflags|NEED_BRACE);
272                         level--;
273                         break;
274         
275                 case TPAR:
276                         p_keyword("(",BEGIN);
277                         p_tree(t->par.partre,0); 
278                         p_keyword(")",END);
279                         break;
280
281                 case TARITH:
282                 {
283                         register struct argnod *ap = t->ar.arexpr;
284                         if(begin_line && level)
285                                 sfnputc(outfile,'\t',level);
286                         sfprintf(outfile,"(( %s ))%c",ap->argflag&ARG_RAW?sh_fmtq(ap->argval):ap->argval,end_line);
287                         if(!(tflags&NO_NEWLINE))
288                                 begin_line=1;
289                         break;
290                 }
291
292                 case TFOR:
293                         cp = (t->tre.tretyp==TSELECT?"select":"for");
294                         p_keyword(cp,BEGIN);
295                         sfputr(outfile,t->for_.fornam,' ');
296                         if(t->for_.forlst)
297                         {
298                                 sfputr(outfile,"in",' ');
299                                 tflags = end_line;
300                                 end_line = '\n';
301                                 p_comarg(t->for_.forlst);
302                                 end_line = tflags;
303                         }
304                         else
305                                 sfputc(outfile,'\n');
306                         begin_line = 1;
307                         t = t->par.partre;
308                 dolist:
309                         p_keyword("do",MIDDLE);
310                         p_tree(t,0);
311                         p_keyword("done",END);
312                         break;
313         
314                 case TSW:
315                         p_keyword("case",BEGIN);
316                         p_arg(t->sw.swarg,' ',0);
317                         if(t->sw.swlst)
318                         {
319                                 begin_line = 1;
320                                 sfputr(outfile,"in",'\n');
321                                 tflags = end_line;
322                                 end_line = '\n';
323                                 p_switch(t->sw.swlst);
324                                 end_line = tflags;
325                         }
326                         p_keyword("esac",END);
327                         break;
328
329                 case TFUN:
330                         if(t->tre.tretyp&FPOSIX)
331                         {
332                                 sfprintf(outfile,"%s",t->funct.functnam);
333                                 p_keyword("()\n",BEGIN);
334                         }
335                         else
336                         {
337                                 p_keyword("function",BEGIN);
338                                 tflags = (t->funct.functargs?' ':'\n');
339                                 sfputr(outfile,t->funct.functnam,tflags);
340                                 if(t->funct.functargs)
341                                 {
342                                         tflags = end_line;
343                                         end_line = '\n';
344                                         p_comarg(t->funct.functargs);
345                                         end_line = tflags;
346                                 }
347                         }
348                         begin_line = 1;
349                         p_keyword("{\n",MIDDLE);
350                         begin_line = 1;
351                         p_tree(t->funct.functtre,0); 
352                         p_keyword("}",END);
353                         break;
354                 /* new test compound command */
355                 case TTST:
356                         p_keyword("[[",BEGIN);
357                         if((t->tre.tretyp&TPAREN)==TPAREN)
358                         {
359                                 p_keyword("(",BEGIN);
360                                 p_tree(t->funct.functtre,0); 
361                                 p_keyword(")",END);
362                         }
363                         else
364                         {
365                                 tflags = (t->tre.tretyp)>>TSHIFT;
366                                 if(t->tre.tretyp&TNEGATE)
367                                         sfputr(outfile,"!",' ');
368                                 if(t->tre.tretyp&TUNARY)
369                                 {
370                                         un_op[1] = tflags;
371                                         sfputr(outfile,un_op,' ');
372                                 }
373                                 else
374                                         cp = ((char*)(shtab_testops+(tflags&037)-1)->sh_name);
375                                 p_arg(&(t->lst.lstlef->arg),' ',0);
376                                 if(t->tre.tretyp&TBINARY)
377                                 {
378                                         sfputr(outfile,cp,' ');
379                                         p_arg(&(t->lst.lstrit->arg),' ',0);
380                                 }
381                         }
382                         p_keyword("]]",END);
383         }
384         while(begin_line && here_doc)
385         {
386                 here_body(here_doc);
387                 here_doc = 0;
388         }
389         end_line = save;
390         return;
391 }
392
393 /*
394  * print a keyword
395  * increment indent level for flag==BEGIN
396  * decrement indent level for flag==END
397  */
398 static void p_keyword __PARAM__((const char *word,int flag), (word, flag)) __OTORP__(const char *word;int flag;){
399         register int sep;
400         if(flag==END)
401                 sep = end_line;
402         else if(*word=='[')
403                 sep = ' ';
404         else
405                 sep = '\t';
406         if(flag!=BEGIN)
407                 level--;
408         if(begin_line && level)
409                 sfnputc(outfile,'\t',level);
410         sfputr(outfile,word,sep);
411         if(sep=='\n')
412                 begin_line=1;
413         else
414                 begin_line=0;
415         if(flag!=END)
416                 level++;
417 }
418
419 static void p_arg __PARAM__((register const struct argnod *arg,register int endchar,int opts), (arg, endchar, opts)) __OTORP__(register const struct argnod *arg;register int endchar;int opts;){
420         register const char *cp;
421         register int flag;
422         do
423         {
424                 if(!arg->argnxt.ap)
425                         flag = endchar;
426                 else if(opts&PRE)
427                 {
428                         /* case alternation lists in reverse order */
429                         p_arg(arg->argnxt.ap,'|',opts);
430                         flag = endchar;
431                 }
432                 else if(opts)
433                         flag = ' ';
434                 cp = arg->argval;
435                 if(*cp==0)
436                 {
437                         /* compound assignment */
438                         struct fornod *fp=(struct fornod*)arg->argchn.ap;
439                         sfprintf(outfile,"%s=(\n",fp->fornam);
440                         sfnputc(outfile,'\t',++level);
441                         p_tree(fp->fortre,0);
442                         if(--level)
443                                 sfnputc(outfile,'\t',level);
444                         sfputc(outfile,')');
445                 }
446                 else if((arg->argflag&ARG_RAW) && (cp[1] || (*cp!='[' && *cp!=']')))
447                         cp = sh_fmtq(cp);
448                 sfputr(outfile,cp,flag);
449                 if(flag=='\n')
450                         begin_line = 1;
451                 arg = arg->argnxt.ap;
452         }
453         while((opts&POST) && arg);
454         return;
455 }
456
457 static void p_redirect __PARAM__((register const struct ionod *iop), (iop)) __OTORP__(register const struct ionod *iop;){
458         register int iof;
459         register char *cp;
460         for(;iop;iop=iop->ionxt)
461         {
462                 iof=iop->iofile;
463                 cp = io_op;
464                 *cp = '0'+(iof&IOUFD);
465                 if(iof&IOPUT)
466                 {
467                         if(*cp == '1')
468                                 cp++;
469                         io_op[1] = '>';
470                 }
471                 else
472                 {
473                         if(*cp == '0')
474                                 cp++;
475                         io_op[1] = '<';
476                 }
477                 io_op[2] = 0;
478                 io_op[3] = 0;
479                 if(iof&IOMOV)
480                         io_op[2] = '&';
481                 else if(iof&(IORDW|IOAPP))
482                         io_op[2] = '>';
483                 else if(iof&IOCLOB)
484                         io_op[2] = '|';
485                 if(iop->iodelim)
486                 {
487                         /* here document */
488 #ifdef xxx
489                         iop->iolink = (char*)here_doc;
490 #endif
491                         here_doc  = iop;
492                         io_op[2] = '<';
493 #ifdef future
494                         if(iof&IOSTRIP)
495                                 io_op[3] = '-';
496 #endif
497                 }
498                 sfputr(outfile,cp,' ');
499                 if(iop->ionxt)
500                         iof = ' ';
501                 else
502                 {
503                         if((iof=end_line)=='\n')
504                                 begin_line = 1;
505                 }
506                 if(iop->iodelim)
507                 {
508                         if(!(iop->iofile&IODOC))
509                                 sfwrite(outfile,"''",2);
510                         sfputr(outfile,sh_fmtq(iop->iodelim),iof);
511                 }
512                 else if(iop->iofile&IORAW)
513                         sfputr(outfile,sh_fmtq(iop->ioname),iof);
514                 else
515                         sfputr(outfile,iop->ioname,iof);
516         }
517         return;
518 }
519
520 static void p_comarg __PARAM__((const register struct comnod *com), (com)) __OTORP__(const register struct comnod *com;){
521         register int flag = end_line;
522         if(com->comarg || com->comio)
523                 flag = ' ';
524         if(com->comset)
525                 p_arg(com->comset,flag,POST);
526         if(com->comarg)
527         {
528                 if(!com->comio)
529                         flag = end_line;
530                 if(com->comtyp&COMSCAN)
531                         p_arg(com->comarg,flag,POST);
532                 else
533                         p_comlist((struct dolnod*)com->comarg,flag);
534         }
535         if(com->comio)
536                 p_redirect(com->comio);
537         return;
538 }
539
540 static void p_comlist __PARAM__((const struct dolnod *dol,int endchar), (dol, endchar)) __OTORP__(const struct dolnod *dol;int endchar;){
541         register char *cp, *const*argv;
542         register int flag = ' ', special;
543         argv = dol->dolval+ARG_SPARE;
544         cp = *argv;
545         special = (*cp=='[' && cp[1]==0);
546         do
547         {
548                 if(cp)
549                         argv++;
550                 else
551                         cp = "";
552                 if(*argv==0)
553                 {
554                         if((flag=endchar)=='\n')
555                                 begin_line = 1;
556                         special = (*cp==']' && cp[1]==0);
557                 }
558                 sfputr(outfile,special?cp:sh_fmtq(cp),flag);
559                 special = 0;
560         }
561         while(cp  = *argv);
562         return;
563 }
564
565 static void p_switch __PARAM__((register const struct regnod *reg), (reg)) __OTORP__(register const struct regnod *reg;){
566         if(level>1)
567                 sfnputc(outfile,'\t',level-1);
568         p_arg(reg->regptr,')',PRE);
569         begin_line = 0;
570         sfputc(outfile,'\t');
571         if(reg->regcom)
572                 p_tree(reg->regcom,0);
573         level++;
574         if(reg->regflag)
575                 p_keyword(";&",END);
576         else
577                 p_keyword(";;",END);
578         if(reg->regnxt)
579                 p_switch(reg->regnxt);
580         return;
581 }
582
583 /*
584  * output here documents
585  */
586 static void here_body __PARAM__((register const struct ionod *iop), (iop)) __OTORP__(register const struct ionod *iop;){
587         Sfio_t *infile;
588 #ifdef xxx
589         if(iop->iolink)
590                 here_body((struct inode*)iop->iolink);
591         iop->iolink = 0;
592 #endif
593         if(iop->iofile&IOSTRG)
594                 infile = sfnew((Sfio_t*)0,iop->ioname,iop->iosize,-1,SF_STRING|SF_READ);
595         else
596                 sfseek(infile=sh.heredocs,iop->iooffset,SEEK_SET);
597         sfmove(infile,outfile,iop->iosize,-1);
598         if(iop->iofile&IOSTRG)
599                 sfclose(infile);
600         sfputr(outfile,iop->iodelim,'\n');
601 }
602