1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*	$NetBSD: expand.c,v 1.68.2.2 2005/04/07 11:37:39 tron Exp $	*/
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*-
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (c) 1991, 1993
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * This code is derived from software contributed to Berkeley by
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Kenneth Almquist.
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redistribution and use in source and binary forms, with or without
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * modification, are permitted provided that the following conditions
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * are met:
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    documentation and/or other materials provided with the distribution.
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 3. Neither the name of the University nor the names of its contributors
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    may be used to endorse or promote products derived from this software
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *    without specific prior written permission.
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * SUCH DAMAGE.
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/cdefs.h>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef lint
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char sccsid[] = "@(#)expand.c	8.5 (Berkeley) 5/15/95";
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project__RCSID("$NetBSD: expand.c,v 1.68.2.2 2005/04/07 11:37:39 tron Exp $");
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* not lint */
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/time.h>
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <dirent.h>
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Routines to expand arguments to commands.  We have to deal with
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * backquotes, shell variables, and file metacharacters.
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "shell.h"
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "main.h"
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "nodes.h"
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "eval.h"
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "expand.h"
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "syntax.h"
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "parser.h"
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "jobs.h"
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "options.h"
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "var.h"
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "input.h"
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "output.h"
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "memalloc.h"
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "error.h"
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mystring.h"
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "show.h"
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Structure specifying which parts of the string should be searched
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * for IFS characters.
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct ifsregion {
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct ifsregion *next;	/* next region in list */
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int begoff;		/* offset of start of region */
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int endoff;		/* offset of end of region */
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int inquotes;		/* search for nul bytes only */
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *expdest;			/* output of current string */
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct nodelist *argbackq;	/* list of back quote expressions */
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct ifsregion ifsfirst;	/* first struct in list of ifs regions */
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct ifsregion *ifslastp;	/* last struct in list */
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct arglist exparg;		/* holds expanded arg list */
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void argstr(char *, int);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *exptilde(char *, int);
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void expbackq(union node *, int, int);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int subevalvar(char *, char *, int, int, int, int);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *evalvar(char *, int);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int varisset(char *, int);
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void varvalue(char *, int, int, int);
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void recordregion(int, int, int);
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void removerecordregions(int);
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void ifsbreakup(char *, struct arglist *);
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void ifsfree(void);
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void expandmeta(struct strlist *, int);
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void expmeta(char *, char *);
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void addfname(char *);
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC struct strlist *expsort(struct strlist *);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC struct strlist *msort(struct strlist *, int);
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int pmatch(char *, char *, int);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *cvtnum(int, char *);
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Expand shell variables and backquotes inside a here document.
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpandhere(union node *arg, int fd)
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	herefd = fd;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	expandarg(arg, (struct arglist *)NULL, 0);
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	xwrite(fd, stackblock(), expdest - stackblock());
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Perform variable substitution and command substitution on an argument,
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * perform splitting and file name expansion.  When arglist is NULL, perform
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * here document expansion.
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpandarg(union node *arg, struct arglist *arglist, int flag)
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *sp;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	argbackq = arg->narg.backquote;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STARTSTACKSTR(expdest);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifsfirst.next = NULL;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp = NULL;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	argstr(arg->narg.text, flag);
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (arglist == NULL) {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;			/* here document expanded */
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STPUTC('\0', expdest);
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = grabstackstr(expdest);
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	exparg.lastp = &exparg.list;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * TODO - EXP_REDIR
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (flag & EXP_FULL) {
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsbreakup(p, &exparg);
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*exparg.lastp = NULL;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		exparg.lastp = &exparg.list;
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		expandmeta(exparg.list, flag);
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			rmescapes(p);
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp = (struct strlist *)stalloc(sizeof (struct strlist));
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp->text = p;
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*exparg.lastp = sp;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		exparg.lastp = &sp->next;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifsfree();
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*exparg.lastp = NULL;
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (exparg.list) {
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*arglist->lastp = exparg.list;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		arglist->lastp = exparg.lastp;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Perform variable and command substitution.
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If EXP_FULL is set, output CTLESC characters to allow for further processing.
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Otherwise treat $@ like $* since no splitting will be performed.
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectargstr(char *p, int flag)
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char c;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int firsteq = 1;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *ifs = 0;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int ifs_split = EXP_IFS_SPLIT;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (flag & EXP_IFS_SPLIT)
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifs = ifsset() ? ifsval() : " \t\n";
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = exptilde(p, flag);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (;;) {
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		switch (c = *p++) {
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case '\0':
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return;
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLQUOTEMARK:
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* "$@" syntax adherence hack */
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((flag & EXP_FULL) != 0)
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(c, expdest);
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifs_split = 0;
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLQUOTEEND:
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifs_split = EXP_IFS_SPLIT;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLESC:
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (quotes)
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(c, expdest);
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			c = *p++;
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(c, expdest);
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLVAR:
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLBACKQ:
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLBACKQ|CTLQUOTE:
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			expbackq(argbackq->n, c & CTLQUOTE, flag);
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			argbackq = argbackq->next;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLENDARI:
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			expari(flag);
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case ':':
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case '=':
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/*
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * sort of a hack - expand tildes in variable
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * assignments (after the first '=' and after ':'s).
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 */
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(c, expdest);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (flag & EXP_VARTILDE && *p == '~') {
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (c == '=') {
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (firsteq)
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						firsteq = 0;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					else
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						break;
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p = exptilde(p, flag);
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		default:
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(c, expdest);
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				/* We need to get the output split here... */
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				recordregion(expdest - stackblock() - 1,
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						expdest - stackblock(), 0);
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexptilde(char *p, int flag)
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char c, *startp = p;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *home;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quotes = flag & (EXP_FULL | EXP_CASE);
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((c = *p) != '\0') {
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		switch(c) {
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLESC:
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return (startp);
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLQUOTEMARK:
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return (startp);
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case ':':
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (flag & EXP_VARTILDE)
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto done;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case '/':
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			goto done;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p++;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectdone:
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*p = '\0';
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*(startp+1) == '\0') {
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if ((home = lookupvar("HOME")) == NULL)
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			goto lose;
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        	goto lose;
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*home == '\0')
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		goto lose;
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*p = c;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while ((c = *home++) != '\0') {
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (quotes && SQSYNTAX[(int)c] == CCTL)
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(CTLESC, expdest);
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STPUTC(c, expdest);
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return (p);
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectlose:
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*p = c;
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return (startp);
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectremoverecordregions(int endoff)
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ifslastp == NULL)
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ifsfirst.endoff > endoff) {
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (ifsfirst.next != NULL) {
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			struct ifsregion *ifsp;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			INTOFF;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifsp = ifsfirst.next->next;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ckfree(ifsfirst.next);
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifsfirst.next = ifsp;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			INTON;
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (ifsfirst.begoff > endoff)
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifslastp = NULL;
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else {
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifslastp = &ifsfirst;
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifsfirst.endoff = endoff;
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp = &ifsfirst;
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (ifslastp->next && ifslastp->next->begoff < endoff)
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifslastp=ifslastp->next;
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (ifslastp->next != NULL) {
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		struct ifsregion *ifsp;
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTOFF;
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsp = ifslastp->next->next;
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ckfree(ifslastp->next);
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifslastp->next = ifsp;
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ifslastp->endoff > endoff)
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifslastp->endoff = endoff;
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Expand arithmetic expression.  Backup to start of expression,
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * evaluate, place result in (backed up) result, adjust string position.
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpari(int flag)
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p, *start;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int result;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int begoff;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quotes = flag & (EXP_FULL | EXP_CASE);
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quoted;
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*	ifsfree(); */
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * This routine is slightly over-complicated for
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * efficiency.  First we make sure there is
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * enough space for the result, which may be bigger
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * than the expression if we add exponentation.  Next we
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * scan backwards looking for the start of arithmetic.  If the
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * next previous character is a CTLESC character, then we
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * have to rescan starting from the beginning since CTLESC
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * characters have to be processed left to right.
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if INT_MAX / 1000000000 >= 10 || INT_MIN / 1000000000 <= -10
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#error "integers with more than 10 digits are not supported"
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	CHECKSTRSPACE(12 - 2, expdest);
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	USTPUTC('\0', expdest);
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	start = stackblock();
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = expdest - 1;
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (*p != CTLARI && p >= start)
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		--p;
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*p != CTLARI)
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		error("missing CTLARI (shouldn't happen)");
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (p > start && *(p-1) == CTLESC)
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (p = start; *p != CTLARI; p++)
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == CTLESC)
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (p[1] == '"')
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		quoted=1;
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	else
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		quoted=0;
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	begoff = p - start;
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	removerecordregions(begoff);
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (quotes)
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		rmescapes(p+2);
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	result = arith(p+2);
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	fmtstr(p, 12, "%d", result);
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (*p++)
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		;
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (quoted == 0)
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		recordregion(begoff, p - 1 - start, 0);
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	result = expdest - p + 1;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STADJUST(-result, expdest);
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Expand stuff in backwards quotes.
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpbackq(union node *cmd, int quoted, int flag)
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct backcmd in;
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int i;
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char buf[128];
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *dest = expdest;
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct ifsregion saveifs, *savelastp;
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct nodelist *saveargbackq;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char lastc;
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int startloc = dest - stackblock();
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int saveherefd;
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quotes = flag & (EXP_FULL | EXP_CASE);
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTOFF;
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	saveifs = ifsfirst;
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	savelastp = ifslastp;
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	saveargbackq = argbackq;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	saveherefd = herefd;
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	herefd = -1;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = grabstackstr(dest);
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	evalbackcmd(cmd, &in);
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ungrabstackstr(p, dest);
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifsfirst = saveifs;
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp = savelastp;
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	argbackq = saveargbackq;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	herefd = saveherefd;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = in.buf;
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	lastc = '\0';
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (;;) {
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (--in.nleft < 0) {
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (in.fd < 0)
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			TRACE(("expbackq: read returns %d\n", i));
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (i <= 0)
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			p = buf;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			in.nleft = i - 1;
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		lastc = *p++;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (lastc != '\0') {
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (quotes && syntax[(int)lastc] == CCTL)
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(CTLESC, dest);
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(lastc, dest);
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/* Eat all trailing newlines */
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = stackblock() + startloc;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (dest > p && dest[-1] == '\n')
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STUNPUTC(dest);
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (in.fd >= 0)
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		close(in.fd);
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (in.buf)
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ckfree(in.buf);
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (in.jp)
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		back_exitstatus = waitforjob(in.jp);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (quoted == 0)
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		recordregion(startloc, dest - stackblock(), 0);
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	TRACE(("evalbackq: size=%d: \"%.*s\"\n",
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		(dest - stackblock()) - startloc,
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		(dest - stackblock()) - startloc,
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		stackblock() + startloc));
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	expdest = dest;
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	INTON;
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectsubevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags)
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *startp;
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *loc = NULL;
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *q;
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int c = 0;
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int saveherefd = herefd;
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct nodelist *saveargbackq = argbackq;
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int amount;
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	herefd = -1;
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	argstr(p, 0);
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STACKSTRNUL(expdest);
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	herefd = saveherefd;
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	argbackq = saveargbackq;
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	startp = stackblock() + startloc;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (str == NULL)
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	    str = stackblock() + strloc;
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	switch (subtype) {
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSASSIGN:
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		setvar(str, startp, 0);
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		amount = startp - expdest;
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STADJUST(amount, expdest);
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		varflags &= ~VSNUL;
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (c != 0)
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*loc = c;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 1;
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSQUESTION:
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (*p != CTLENDVAR) {
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			outfmt(&errout, "%s\n", startp);
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error((char *)NULL);
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		error("%.*s: parameter %snot set", p - str - 1,
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		      str, (varflags & VSNUL) ? "null or "
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					      : nullstr);
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* NOTREACHED */
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMLEFT:
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (loc = startp; loc < str; loc++) {
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			c = *loc;
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*loc = '\0';
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (patmatch(str, startp, varflags & VSQUOTE))
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto recordleft;
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*loc = c;
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((varflags & VSQUOTE) && *loc == CTLESC)
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			        loc++;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 0;
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMLEFTMAX:
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (loc = str - 1; loc >= startp;) {
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			c = *loc;
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*loc = '\0';
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (patmatch(str, startp, varflags & VSQUOTE))
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto recordleft;
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*loc = c;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			loc--;
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((varflags & VSQUOTE) && loc > startp &&
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			    *(loc - 1) == CTLESC) {
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				for (q = startp; q < loc; q++)
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (*q == CTLESC)
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						q++;
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (q > loc)
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					loc--;
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 0;
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMRIGHT:
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	        for (loc = str - 1; loc >= startp;) {
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (patmatch(str, loc, varflags & VSQUOTE))
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto recordright;
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			loc--;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((varflags & VSQUOTE) && loc > startp &&
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			    *(loc - 1) == CTLESC) {
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				for (q = startp; q < loc; q++)
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (*q == CTLESC)
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						q++;
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (q > loc)
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					loc--;
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 0;
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMRIGHTMAX:
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (loc = startp; loc < str - 1; loc++) {
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (patmatch(str, loc, varflags & VSQUOTE))
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto recordright;
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((varflags & VSQUOTE) && *loc == CTLESC)
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			        loc++;
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 0;
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	default:
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		abort();
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrecordleft:
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*loc = c;
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	amount = ((str - 1) - (loc - startp)) - expdest;
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STADJUST(amount, expdest);
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (loc != str - 1)
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*startp++ = *loc++;
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return 1;
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrecordright:
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	amount = loc - expdest;
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STADJUST(amount, expdest);
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STPUTC('\0', expdest);
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	STADJUST(-1, expdest);
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return 1;
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Expand a variable, and return a pointer to the next character in the
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * input string.
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC char *
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectevalvar(char *p, int flag)
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int subtype;
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int varflags;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *var;
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *val;
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int patloc;
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int c;
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int set;
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int special;
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int startloc;
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int varlen;
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int apply_ifs;
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int quotes = flag & (EXP_FULL | EXP_CASE);
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	varflags = (unsigned char)*p++;
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	subtype = varflags & VSTYPE;
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	var = p;
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	special = !is_name(*p);
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = strchr(p, '=') + 1;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectagain: /* jump here after setting a variable with ${var=text} */
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (special) {
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		set = varisset(var, varflags & VSNUL);
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		val = NULL;
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		val = lookupvar(var);
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			val = NULL;
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			set = 0;
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			set = 1;
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	varlen = 0;
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	startloc = expdest - stackblock();
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (!set && uflag) {
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		switch (subtype) {
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSNORMAL:
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSTRIMLEFT:
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSTRIMLEFTMAX:
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSTRIMRIGHT:
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSTRIMRIGHTMAX:
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case VSLENGTH:
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			error("%.*s: parameter not set", p - var - 1, var);
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* NOTREACHED */
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (set && subtype != VSPLUS) {
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* insert the value of the variable */
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (special) {
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			varvalue(var, varflags & VSQUOTE, subtype, flag);
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (subtype == VSLENGTH) {
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				varlen = expdest - stackblock() - startloc;
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STADJUST(-varlen, expdest);
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else {
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project								  : BASESYNTAX;
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (subtype == VSLENGTH) {
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				for (;*val; val++)
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					varlen++;
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			} else {
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				while (*val) {
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (quotes && syntax[(int)*val] == CCTL)
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						STPUTC(CTLESC, expdest);
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					STPUTC(*val++, expdest);
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	apply_ifs = ((varflags & VSQUOTE) == 0 ||
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		(*var == '@' && shellparam.nparam != 1));
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	switch (subtype) {
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSLENGTH:
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		expdest = cvtnum(varlen, expdest);
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSNORMAL:
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSPLUS:
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		set = !set;
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* FALLTHROUGH */
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSMINUS:
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (!set) {
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		        argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/*
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * ${x-a b c} doesn't get split, but removing the
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * ${x-'a b' c} should generate 2 args.
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 */
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* We should have marked stuff already */
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			apply_ifs = 0;
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMLEFT:
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMLEFTMAX:
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMRIGHT:
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSTRIMRIGHTMAX:
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (!set)
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/*
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		 * Terminate the string and start recording the pattern
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		 * right after it
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		 */
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STPUTC('\0', expdest);
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		patloc = expdest - stackblock();
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (subevalvar(p, NULL, patloc, subtype,
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			       startloc, varflags) == 0) {
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			int amount = (expdest - stackblock() - patloc) + 1;
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STADJUST(-amount, expdest);
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* Remove any recorded regions beyond start of variable */
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		removerecordregions(startloc);
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		apply_ifs = 1;
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSASSIGN:
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case VSQUESTION:
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (set)
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			varflags &= ~VSNUL;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/*
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * Remove any recorded regions beyond
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * start of variable
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 */
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			removerecordregions(startloc);
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			goto again;
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		apply_ifs = 0;
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	default:
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		abort();
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (apply_ifs)
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		recordregion(startloc, expdest - stackblock(),
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			     varflags & VSQUOTE);
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (subtype != VSNORMAL) {	/* skip to end of alternative */
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		int nesting = 1;
757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (;;) {
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((c = *p++) == CTLESC)
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (set)
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					argbackq = argbackq->next;
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			} else if (c == CTLVAR) {
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if ((*p++ & VSTYPE) != VSNORMAL)
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					nesting++;
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			} else if (c == CTLENDVAR) {
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (--nesting == 0)
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					break;
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return p;
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Test whether a specialized variable is set.
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvarisset(char *name, int nulok)
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*name == '!')
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return backgndpid != -1;
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	else if (*name == '@' || *name == '*') {
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (*shellparam.p == NULL)
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return 0;
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (nulok) {
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			char **av;
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			for (av = shellparam.p; *av; av++)
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (**av != '\0')
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					return 1;
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return 0;
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else if (is_digit(*name)) {
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		char *ap;
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		int num = atoi(name);
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (num > shellparam.nparam)
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return 0;
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
805dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (num == 0)
806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ap = arg0;
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else
808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ap = shellparam.p[num - 1];
809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (nulok && (ap == NULL || *ap == '\0'))
811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return 0;
812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return 1;
814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
817dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
819dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Add the value of a specialized variable to the stack string.
820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvarvalue(char *name, int quoted, int subtype, int flag)
824dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
825dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int num;
826dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
827dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int i;
828dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char sep;
829dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char **ap;
830dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char const *syntax;
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
832dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define STRTODEST(p) \
833dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	do {\
834dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \
835dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		syntax = quoted? DQSYNTAX : BASESYNTAX; \
836dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (*p) { \
837dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (syntax[(int)*p] == CCTL) \
838dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(CTLESC, expdest); \
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(*p++, expdest); \
840dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} \
841dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else \
842dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (*p) \
843dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STPUTC(*p++, expdest); \
844dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} while (0)
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	switch (*name) {
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '$':
849dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		num = rootpid;
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		goto numvar;
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '?':
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		num = exitstatus;
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		goto numvar;
854dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '#':
855dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		num = shellparam.nparam;
856dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		goto numvar;
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '!':
858dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		num = backgndpid;
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnumvar:
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		expdest = cvtnum(num, expdest);
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '-':
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (i = 0; optlist[i].name; i++) {
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (optlist[i].val)
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(optlist[i].letter, expdest);
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '@':
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (flag & EXP_FULL && quoted) {
870dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STRTODEST(p);
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (*ap)
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					STPUTC('\0', expdest);
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* fall through */
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '*':
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (ifsset() != 0)
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			sep = ifsval()[0];
881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else
882dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			sep = ' ';
883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			STRTODEST(p);
885dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*ap && sep)
886dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STPUTC(sep, expdest);
887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
889dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	case '0':
890dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = arg0;
891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		STRTODEST(p);
892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
893dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	default:
894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (is_digit(*name)) {
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			num = atoi(name);
896dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (num > 0 && num <= shellparam.nparam) {
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p = shellparam.p[num - 1];
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				STRTODEST(p);
899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		break;
902dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
904dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
905dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
906dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
907dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
908dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Record the fact that we have to scan this region of the
909dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * string for IFS characters.
910dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
911dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectrecordregion(int start, int end, int inquotes)
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct ifsregion *ifsp;
916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ifslastp == NULL) {
918dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsp = &ifsfirst;
919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (ifslastp->endoff == start
921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		    && ifslastp->inquotes == inquotes) {
922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* extend previous area */
923dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			ifslastp->endoff = end;
924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			return;
925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifslastp->next = ifsp;
928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp = ifsp;
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp->next = NULL;
931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp->begoff = start;
932dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp->endoff = end;
933dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp->inquotes = inquotes;
934dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
935dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
937dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Break the argument string into pieces based upon IFS and add the
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * strings to the argument list.  The regions of the string to be
941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * searched for IFS characters have been stored by recordregion.
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifsbreakup(char *string, struct arglist *arglist)
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct ifsregion *ifsp;
947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *sp;
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *start;
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *q;
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *ifs;
952dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *ifsspc;
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int inquotes;
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	start = string;
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifsspc = NULL;
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	inquotes = 0;
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (ifslastp == NULL) {
960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		/* Return entire argument, IFS doesn't apply to any of it */
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp = (struct strlist *)stalloc(sizeof *sp);
962dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp->text = start;
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*arglist->lastp = sp;
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		arglist->lastp = &sp->next;
965dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
967dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
968dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifs = ifsset() ? ifsval() : " \t\n";
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = string + ifsp->begoff;
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		inquotes = ifsp->inquotes;
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsspc = NULL;
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (p < string + ifsp->endoff) {
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			q = p;
976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == CTLESC)
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (inquotes) {
979dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				/* Only NULs (probably from "$@") end args */
980dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (*p != 0) {
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					p++;
982dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					continue;
983dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
984dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			} else {
985dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (!strchr(ifs, *p)) {
986dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					p++;
987dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					continue;
988dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
989dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				ifsspc = strchr(" \t\n", *p);
990dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
991dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				/* Ignore IFS whitespace at start */
992dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (q == start && ifsspc != NULL) {
993dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					p++;
994dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					start = p;
995dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					continue;
996dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
997dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
998dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
999dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/* Save this argument... */
1000dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*q = '\0';
1001dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			sp = (struct strlist *)stalloc(sizeof *sp);
1002dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			sp->text = start;
1003dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*arglist->lastp = sp;
1004dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			arglist->lastp = &sp->next;
1005dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			p++;
1006dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1007dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (ifsspc != NULL) {
1008dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				/* Ignore further trailing IFS whitespace */
1009dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				for (; p < string + ifsp->endoff; p++) {
1010dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					q = p;
1011dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (*p == CTLESC)
1012dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						p++;
1013dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (strchr(ifs, *p) == NULL) {
1014dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						p = q;
1015dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						break;
1016dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					}
1017dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					if (strchr(" \t\n", *p) == NULL) {
1018dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						p++;
1019dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project						break;
1020dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					}
1021dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
1022dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
1023dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			start = p;
1024dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1025dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1026dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1027dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/*
1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * Save anything left as an argument.
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * generating 2 arguments, the second of which is empty.
1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * Some recent clarification of the Posix spec say that it
1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 * should only generate one....
1033dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	 */
1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*start /* || (!ifsspc && start > string) */) {
1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp = (struct strlist *)stalloc(sizeof *sp);
1036dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		sp->text = start;
1037dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*arglist->lastp = sp;
1038dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		arglist->lastp = &sp->next;
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
1043dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifsfree(void)
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (ifsfirst.next != NULL) {
1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		struct ifsregion *ifsp;
1047dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTOFF;
1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsp = ifsfirst.next->next;
1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ckfree(ifsfirst.next);
1050dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ifsfirst.next = ifsp;
1051dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
1052dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1053dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifslastp = NULL;
1054dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	ifsfirst.next = NULL;
1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1056dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1059dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Expand shell metacharacters.  At this point, the only control characters
1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * should be escapes.  The results are stored in the list exparg.
1062dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1063dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1064dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectchar *expdir;
1065dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1066dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1067dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
1068dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpandmeta(struct strlist *str, int flag)
1069dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1070dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist **savelastp;
1072dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *sp;
1073dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char c;
1074dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	/* TODO - EXP_REDIR */
1075dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1076dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (str) {
1077dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (fflag)
1078dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			goto nometa;
1079dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = str->text;
1080dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (;;) {			/* fast check for meta chars */
1081dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((c = *p++) == '\0')
1082dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				goto nometa;
1083dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (c == '*' || c == '?' || c == '[' || c == '!')
1084dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
1085dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1086dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		savelastp = exparg.lastp;
1087dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTOFF;
1088dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (expdir == NULL) {
1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			int i = strlen(str->text);
1090dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
1091dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1092dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1093dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		expmeta(expdir, str->text);
1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		ckfree(expdir);
1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		expdir = NULL;
1096dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		INTON;
1097dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (exparg.lastp == savelastp) {
1098dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			/*
1099dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 * no matches
1100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			 */
1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnometa:
1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*exparg.lastp = str;
1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			rmescapes(str->text);
1104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			exparg.lastp = &str->next;
1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else {
1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*exparg.lastp = NULL;
1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*savelastp = sp = expsort(*savelastp);
1108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			while (sp->next != NULL)
1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				sp = sp->next;
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			exparg.lastp = &sp->next;
1111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		str = str->next;
1113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Do metacharacter (i.e. *, ?, [...]) expansion.
1119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
1122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpmeta(char *enddir, char *name)
1123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
1125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	const char *cp;
1126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *q;
1127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *start;
1128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *endname;
1129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int metaflag;
1130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct stat statb;
1131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	DIR *dirp;
1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct dirent *dp;
1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int atend;
1134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int matchdot;
1135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	metaflag = 0;
1137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	start = name;
1138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (p = name ; ; p++) {
1139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (*p == '*' || *p == '?')
1140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			metaflag = 1;
1141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else if (*p == '[') {
1142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			q = p + 1;
1143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*q == '!')
1144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				q++;
1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			for (;;) {
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				while (*q == CTLQUOTEMARK)
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					q++;
1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (*q == CTLESC)
1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					q++;
1150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (*q == '/' || *q == '\0')
1151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					break;
1152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				if (*++q == ']') {
1153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					metaflag = 1;
1154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					break;
1155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				}
1156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
1157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else if (*p == '!' && p[1] == '!'	&& (p == name || p[-1] == '/')) {
1158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			metaflag = 1;
1159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else if (*p == '\0')
1160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
1161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else if (*p == CTLQUOTEMARK)
1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		else if (*p == CTLESC)
1164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			p++;
1165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (*p == '/') {
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (metaflag)
1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
1168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			start = p + 1;
1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (metaflag == 0) {	/* we've reached the end of the file name */
1172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (enddir != expdir)
1173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			metaflag++;
1174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		for (p = name ; ; p++) {
1175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == CTLQUOTEMARK)
1176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				continue;
1177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == CTLESC)
1178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
1179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*enddir++ = *p;
1180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == '\0')
1181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
1182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (metaflag == 0 || lstat(expdir, &statb) >= 0)
1184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			addfname(expdir);
1185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
1186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	endname = p;
1188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (start != name) {
1189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = name;
1190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		while (p < start) {
1191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			while (*p == CTLQUOTEMARK)
1192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
1193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*p == CTLESC)
1194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p++;
1195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*enddir++ = *p++;
1196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (enddir == expdir) {
1199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cp = ".";
1200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else if (enddir == expdir + 1 && *expdir == '/') {
1201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cp = "/";
1202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
1203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		cp = expdir;
1204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		enddir[-1] = '\0';
1205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if ((dirp = opendir(cp)) == NULL)
1207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return;
1208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (enddir != expdir)
1209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		enddir[-1] = '/';
1210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*endname == 0) {
1211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		atend = 1;
1212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	} else {
1213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		atend = 0;
1214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		*endname++ = '\0';
1215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	matchdot = 0;
1217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = start;
1218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (*p == CTLQUOTEMARK)
1219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p++;
1220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*p == CTLESC)
1221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p++;
1222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (*p == '.')
1223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		matchdot++;
1224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	while (! int_pending() && (dp = readdir(dirp)) != NULL) {
1225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (dp->d_name[0] == '.' && ! matchdot)
1226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
1227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (patmatch(start, dp->d_name, 0)) {
1228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (atend) {
1229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				scopy(dp->d_name, enddir);
1230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				addfname(expdir);
1231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			} else {
1232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				for (p = enddir, cp = dp->d_name;
1233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				     (*p++ = *cp++) != '\0';)
1234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project					continue;
1235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				p[-1] = '/';
1236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				expmeta(p, endname);
1237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
1238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	closedir(dirp);
1241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (! atend)
1242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		endname[-1] = '/';
1243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Add a file name to the list.
1248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC void
1251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectaddfname(char *name)
1252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p;
1254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *sp;
1255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = stalloc(strlen(name) + 1);
1257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	scopy(name, p);
1258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	sp = (struct strlist *)stalloc(sizeof *sp);
1259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	sp->text = p;
1260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	*exparg.lastp = sp;
1261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	exparg.lastp = &sp->next;
1262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Sort the results of file name expansion.  It calculates the number of
1267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * strings to sort and then calls msort (short for merge sort) to do the
1268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * work.
1269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC struct strlist *
1272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectexpsort(struct strlist *str)
1273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int len;
1275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *sp;
1276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	len = 0;
1278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (sp = str ; sp ; sp = sp->next)
1279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		len++;
1280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return msort(str, len);
1281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC struct strlist *
1285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectmsort(struct strlist *list, int len)
1286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist *p, *q = NULL;
1288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	struct strlist **lpp;
1289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int half;
1290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	int n;
1291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (len <= 1)
1293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return list;
1294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	half = len >> 1;
1295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = list;
1296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (n = half ; --n >= 0 ; ) {
1297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		q = p;
1298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		p = p->next;
1299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	q->next = NULL;			/* terminate first half of list */
1301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	q = msort(list, half);		/* sort first half of list */
1302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = msort(p, len - half);		/* sort second half */
1303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	lpp = &list;
1304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (;;) {
1305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		if (strcmp(p->text, q->text) < 0) {
1306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*lpp = p;
1307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			lpp = &p->next;
1308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((p = *lpp) == NULL) {
1309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				*lpp = q;
1310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
1311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
1312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		} else {
1313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			*lpp = q;
1314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			lpp = &q->next;
1315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if ((q = *lpp) == NULL) {
1316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				*lpp = p;
1317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				break;
1318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			}
1319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		}
1320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	}
1321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	return list;
1322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
1327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Returns true if the pattern matches the string.
1328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
1329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint
1331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectpatmatch(char *pattern, char *string, int squoted)
1332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef notdef
1334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	if (pattern[0] == '!' && pattern[1] == '!')
1335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return 1 - pmatch(pattern + 2, string);
1336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	else
1337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
1338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		return pmatch(pattern, string, squoted);
1339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source ProjectSTATIC int
1343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectpmatch(char *pattern, char *string, int squoted)
1344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
1345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char *p, *q;
1346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	char c;
1347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	p = pattern;
1349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	q = string;
1350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project	for (;;) {
1351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		switch (c = *p++) {
1352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case '\0':
1353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			goto breakloop;
1354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLESC:
1355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (squoted && *q == CTLESC)
1356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				q++;
1357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*q++ != *p++)
1358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				return 0;
1359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			break;
1360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case CTLQUOTEMARK:
1361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			continue;
1362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project		case '?':
1363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (squoted && *q == CTLESC)
1364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project				q++;
1365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project			if (*q++ == '\0')
1366