xref: /illumos-gate/usr/src/cmd/sh/func.c (revision afab0816ecb604f0099a09ad8ee398f0d7b77b1c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * UNIX shell
32  */
33 
34 #include	"defs.h"
35 
36 static void free_arg(struct argnod *);
37 static void freeio(struct ionod *);
38 static void freereg(struct regnod *);
39 static void prarg(struct argnod *argp);
40 static void prio(struct ionod *iop);
41 
42 void
43 freefunc(struct namnod 	*n)
44 {
45 	freetree((struct trenod *)(n->namenv));
46 }
47 
48 void
49 freetree(struct trenod *t)
50 {
51 	if (t)
52 	{
53 		int type;
54 
55 		type = t->tretyp & COMMSK;
56 
57 		switch (type)
58 		{
59 			case TFND: {
60 				struct fndnod *f = fndptr(t);
61 
62 				if (f->fndref > 0) {
63 					f->fndref--;
64 					return;
65 				}
66 				free(f->fndnam);
67 				freetree(f->fndval);
68 				break;
69 			}
70 
71 			case TCOM:
72 				freeio(comptr(t)->comio);
73 				free_arg(comptr(t)->comarg);
74 				free_arg(comptr(t)->comset);
75 				break;
76 
77 			case TFORK:
78 				freeio(forkptr(t)->forkio);
79 				freetree(forkptr(t)->forktre);
80 				break;
81 
82 			case TPAR:
83 				freetree(parptr(t)->partre);
84 				break;
85 
86 			case TFIL:
87 			case TLST:
88 			case TAND:
89 			case TORF:
90 				freetree(lstptr(t)->lstlef);
91 				freetree(lstptr(t)->lstrit);
92 				break;
93 
94 			case TFOR:
95 			{
96 				struct fornod *f = (struct fornod *)t;
97 
98 				free(f->fornam);
99 				freetree(f->fortre);
100 				if (f->forlst)
101 				{
102 					freeio(f->forlst->comio);
103 					free_arg(f->forlst->comarg);
104 					free_arg(f->forlst->comset);
105 					free(f->forlst);
106 				}
107 			}
108 			break;
109 
110 			case TWH:
111 			case TUN:
112 				freetree(whptr(t)->whtre);
113 				freetree(whptr(t)->dotre);
114 				break;
115 
116 			case TIF:
117 				freetree(ifptr(t)->iftre);
118 				freetree(ifptr(t)->thtre);
119 				freetree(ifptr(t)->eltre);
120 				break;
121 
122 			case TSW:
123 				free(swptr(t)->swarg);
124 				freereg(swptr(t)->swlst);
125 				break;
126 		}
127 		free(t);
128 	}
129 }
130 
131 static void
132 free_arg(struct argnod *argp)
133 {
134 	struct argnod 	*sav;
135 
136 	while (argp)
137 	{
138 		sav = argp->argnxt;
139 		free(argp);
140 		argp = sav;
141 	}
142 }
143 
144 void
145 freeio(struct ionod *iop)
146 {
147 	struct ionod *sav;
148 
149 	while (iop)
150 	{
151 		if (iop->iofile & IODOC)
152 		{
153 
154 #ifdef DEBUG
155 			prs("unlinking ");
156 			prs(iop->ioname);
157 			newline();
158 #endif
159 
160 			unlink(iop->ioname);
161 
162 			if (fiotemp == iop)
163 				fiotemp = iop->iolst;
164 			else
165 			{
166 				struct ionod *fiop = fiotemp;
167 
168 				while (fiop->iolst != iop)
169 					fiop = fiop->iolst;
170 
171 				fiop->iolst = iop->iolst;
172 			}
173 		}
174 		free(iop->ioname);
175 		free(iop->iolink);
176 		sav = iop->ionxt;
177 		free(iop);
178 		iop = sav;
179 	}
180 }
181 
182 static void
183 freereg(struct regnod *regp)
184 {
185 	struct regnod 	*sav;
186 
187 	while (regp)
188 	{
189 		free_arg(regp->regptr);
190 		freetree(regp->regcom);
191 		sav = regp->regnxt;
192 		free(regp);
193 		regp = sav;
194 	}
195 }
196 
197 
198 static int nonl = 0;
199 
200 void
201 prbgnlst(void)
202 {
203 	if (nonl)
204 		prc_buff(SPACE);
205 	else
206 		prc_buff(NL);
207 }
208 
209 void
210 prendlst(void)
211 {
212 	if (nonl) {
213 		prc_buff(';');
214 		prc_buff(SPACE);
215 	}
216 	else
217 		prc_buff(NL);
218 }
219 
220 void
221 prcmd(struct trenod *t)
222 {
223 	nonl++;
224 	prf(t);
225 	nonl = 0;
226 }
227 
228 void
229 prf(struct trenod *t)
230 {
231 	sigchk();
232 
233 	if (t)
234 	{
235 		int	type;
236 
237 		type = t->tretyp & COMMSK;
238 
239 		switch(type)
240 		{
241 			case TFND:
242 			{
243 				struct fndnod *f = (struct fndnod *)t;
244 
245 				prs_buff(f->fndnam);
246 				prs_buff("(){");
247 				prbgnlst();
248 				prf(f->fndval);
249 				prbgnlst();
250 				prs_buff("}");
251 				break;
252 			}
253 
254 			case TCOM:
255 				if (comptr(t)->comset) {
256 					prarg(comptr(t)->comset);
257 					prc_buff(SPACE);
258 				}
259 				prarg(comptr(t)->comarg);
260 				prio(comptr(t)->comio);
261 				break;
262 
263 			case TFORK:
264 				prf(forkptr(t)->forktre);
265 				prio(forkptr(t)->forkio);
266 				if (forkptr(t)->forktyp & FAMP)
267 					prs_buff(" &");
268 				break;
269 
270 			case TPAR:
271 				prs_buff("(");
272 				prf(parptr(t)->partre);
273 				prs_buff(")");
274 				break;
275 
276 			case TFIL:
277 				prf(lstptr(t)->lstlef);
278 				prs_buff(" | ");
279 				prf(lstptr(t)->lstrit);
280 				break;
281 
282 			case TLST:
283 				prf(lstptr(t)->lstlef);
284 				prendlst();
285 				prf(lstptr(t)->lstrit);
286 				break;
287 
288 			case TAND:
289 				prf(lstptr(t)->lstlef);
290 				prs_buff(" && ");
291 				prf(lstptr(t)->lstrit);
292 				break;
293 
294 			case TORF:
295 				prf(lstptr(t)->lstlef);
296 				prs_buff(" || ");
297 				prf(lstptr(t)->lstrit);
298 				break;
299 
300 			case TFOR:
301 				{
302 					struct argnod	*arg;
303 					struct fornod 	*f = (struct fornod *)t;
304 
305 					prs_buff("for ");
306 					prs_buff(f->fornam);
307 
308 					if (f->forlst)
309 					{
310 						arg = f->forlst->comarg;
311 						prs_buff(" in");
312 
313 						while(arg != ENDARGS)
314 						{
315 							prc_buff(SPACE);
316 							prs_buff(arg->argval);
317 							arg = arg->argnxt;
318 						}
319 					}
320 
321 					prendlst();
322 					prs_buff("do");
323 					prbgnlst();
324 					prf(f->fortre);
325 					prendlst();
326 					prs_buff("done");
327 				}
328 				break;
329 
330 			case TWH:
331 			case TUN:
332 				if (type == TWH)
333 					prs_buff("while ");
334 				else
335 					prs_buff("until ");
336 				prf(whptr(t)->whtre);
337 				prendlst();
338 				prs_buff("do");
339 				prbgnlst();
340 				prf(whptr(t)->dotre);
341 				prendlst();
342 				prs_buff("done");
343 				break;
344 
345 			case TIF:
346 			{
347 				struct ifnod *f = (struct ifnod *)t;
348 
349 				prs_buff("if ");
350 				prf(f->iftre);
351 				prendlst();
352 				prs_buff("then");
353 				prendlst();
354 				prf(f->thtre);
355 
356 				if (f->eltre)
357 				{
358 					prendlst();
359 					prs_buff("else");
360 					prendlst();
361 					prf(f->eltre);
362 				}
363 
364 				prendlst();
365 				prs_buff("fi");
366 				break;
367 			}
368 
369 			case TSW:
370 				{
371 					struct regnod 	*swl;
372 
373 					prs_buff("case ");
374 					prs_buff(swptr(t)->swarg);
375 
376 					swl = swptr(t)->swlst;
377 					while(swl)
378 					{
379 						struct argnod	*arg = swl->regptr;
380 
381 						if (arg)
382 						{
383 							prs_buff(arg->argval);
384 							arg = arg->argnxt;
385 						}
386 
387 						while(arg)
388 						{
389 							prs_buff(" | ");
390 							prs_buff(arg->argval);
391 							arg = arg->argnxt;
392 						}
393 
394 						prs_buff(")");
395 						prf(swl->regcom);
396 						prs_buff(";;");
397 						swl = swl->regnxt;
398 					}
399 				}
400 				break;
401 			}
402 		}
403 
404 	sigchk();
405 }
406 
407 static void
408 prarg(struct argnod *argp)
409 {
410 	while (argp)
411 	{
412 		prs_buff(argp->argval);
413 		argp=argp->argnxt;
414 		if (argp)
415 			prc_buff(SPACE);
416 	}
417 }
418 
419 static void
420 prio(struct ionod *iop)
421 {
422 	int	iof;
423 	unsigned char	*ion;
424 
425 	while (iop)
426 	{
427 		iof = iop->iofile;
428 		ion = (unsigned char *) iop->ioname;
429 
430 		if (*ion)
431 		{
432 			prc_buff(SPACE);
433 
434 			prn_buff(iof & IOUFD);
435 
436 			if (iof & IODOC)
437 				prs_buff("<<");
438 			else if (iof & IOMOV)
439 			{
440 				if (iof & IOPUT)
441 					prs_buff(">&");
442 				else
443 					prs_buff("<&");
444 
445 			}
446 			else if ((iof & IOPUT) == 0)
447 				prc_buff('<');
448 			else if (iof & IOAPP)
449 				prs_buff(">>");
450 			else
451 				prc_buff('>');
452 
453 			prs_buff(ion);
454 		}
455 		iop = iop->ionxt;
456 	}
457 }
458