summaryrefslogtreecommitdiffstats
path: root/bin/sh/expand.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-09-01 10:22:36 +0000
committerpeter <peter@FreeBSD.org>1996-09-01 10:22:36 +0000
commit5195be912eb257c05a0c97e561e72f01af2583ff (patch)
treee47ab3981b495c675a987dd1e943d1f4c823f314 /bin/sh/expand.c
parent2fc7d7d1fa299368ccdddede67b31695266698bd (diff)
downloadFreeBSD-src-5195be912eb257c05a0c97e561e72f01af2583ff.zip
FreeBSD-src-5195be912eb257c05a0c97e561e72f01af2583ff.tar.gz
Merge of 4.4-Lite2 sh source, plus some gcc -Wall cleaning. This is a
merge of parallel duplicate work by Steve Price and myself. :-] There are some changes to the build that are my fault... mkinit.c was trying (poorly) to duplicate some of the work that make(1) is designed to do. The Makefile hackery is my fault too, the depend list was incomplete because of some explicit OBJS+= entries, so mkdep wasn't picking up their source file #includes. This closes a pile of /bin/sh PR's, but not all of them.. Submitted by: Steve Price <steve@bonsai.hiwaay.net>, peter
Diffstat (limited to 'bin/sh/expand.c')
-rw-r--r--bin/sh/expand.c388
1 files changed, 280 insertions, 108 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index 922ae98..99bbb3c 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -33,13 +33,23 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: expand.c,v 1.5 1996/08/11 22:50:58 ache Exp $
+ * $Id: expand.c,v 1.6 1996/08/12 19:31:11 ache Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)expand.c 8.2 (Berkeley) 10/22/93";
+static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
#endif /* not lint */
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <locale.h>
+
/*
* Routines to expand arguments to commands. We have to deal with
* backquotes, shell variables, and file metacharacters.
@@ -60,13 +70,8 @@ static char sccsid[] = "@(#)expand.c 8.2 (Berkeley) 10/22/93";
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
-#include <sys/types.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <locale.h>
-#include <errno.h>
-#include <dirent.h>
-#include <pwd.h>
+#include "arith.h"
+#include "show.h"
/*
* Structure specifying which parts of the string should be searched
@@ -87,39 +92,22 @@ struct ifsregion ifsfirst; /* first struct in list of ifs regions */
struct ifsregion *ifslastp; /* last struct in list */
struct arglist exparg; /* holds expanded arg list */
-#ifdef __STDC__
-STATIC void argstr(char *, int);
-STATIC void expbackq(union node *, int, int);
-STATIC char *evalvar(char *, int);
-STATIC int varisset(int);
-STATIC void varvalue(int, int, int);
-STATIC void recordregion(int, int, int);
-STATIC void ifsbreakup(char *, struct arglist *);
-STATIC void expandmeta(struct strlist *, int);
-STATIC void expmeta(char *, char *);
-STATIC void expari(int);
-STATIC void addfname(char *);
-STATIC struct strlist *expsort(struct strlist *);
-STATIC struct strlist *msort(struct strlist *, int);
-STATIC int pmatch(char *, char *);
-STATIC char *exptilde(char *, int);
-#else
-STATIC void argstr();
-STATIC void expbackq();
-STATIC char *evalvar();
-STATIC int varisset();
-STATIC void varvalue();
-STATIC void recordregion();
-STATIC void ifsbreakup();
-STATIC void expandmeta();
-STATIC void expmeta();
-STATIC void expari();
-STATIC void addfname();
-STATIC struct strlist *expsort();
-STATIC struct strlist *msort();
-STATIC int pmatch();
-STATIC char *exptilde();
-#endif
+STATIC void argstr __P((char *, int));
+STATIC char *exptilde __P((char *, int));
+STATIC void expbackq __P((union node *, int, int));
+STATIC int subevalvar __P((char *, char *, int, int, int));
+STATIC char *evalvar __P((char *, int));
+STATIC int varisset __P((int));
+STATIC void varvalue __P((int, int, int));
+STATIC void recordregion __P((int, int, int));
+STATIC void ifsbreakup __P((char *, struct arglist *));
+STATIC void expandmeta __P((struct strlist *, int));
+STATIC void expmeta __P((char *, char *));
+STATIC void addfname __P((char *));
+STATIC struct strlist *expsort __P((struct strlist *));
+STATIC struct strlist *msort __P((struct strlist *, int));
+STATIC int pmatch __P((char *, char *));
+STATIC char *cvtnum __P((int, char *));
/*
* Expand shell variables and backquotes inside a here document.
@@ -147,7 +135,8 @@ void
expandarg(arg, arglist, flag)
union node *arg;
struct arglist *arglist;
- {
+ int flag;
+{
struct strlist *sp;
char *p;
@@ -204,7 +193,8 @@ expandarg(arg, arglist, flag)
STATIC void
argstr(p, flag)
register char *p;
- {
+ int flag;
+{
register char c;
int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
int firsteq = 1;
@@ -260,13 +250,14 @@ breakloop:;
STATIC char *
exptilde(p, flag)
char *p;
- {
+ int flag;
+{
char c, *startp = p;
struct passwd *pw;
char *home;
int quotes = flag & (EXP_FULL | EXP_CASE);
- while (c = *p) {
+ while ((c = *p) != '\0') {
switch(c) {
case CTLESC:
return (startp);
@@ -292,7 +283,7 @@ done:
if (*home == '\0')
goto lose;
*p = c;
- while (c = *home++) {
+ while ((c = *home++) != '\0') {
if (quotes && SQSYNTAX[c] == CCTL)
STPUTC(CTLESC, expdest);
STPUTC(c, expdest);
@@ -310,7 +301,8 @@ lose:
*/
void
expari(flag)
- {
+ int flag;
+{
char *p, *start;
int result;
int quotes = flag & (EXP_FULL | EXP_CASE);
@@ -355,7 +347,9 @@ expari(flag)
STATIC void
expbackq(cmd, quoted, flag)
union node *cmd;
- {
+ int quoted;
+ int flag;
+{
struct backcmd in;
int i;
char buf[128];
@@ -403,11 +397,11 @@ expbackq(cmd, quoted, flag)
STPUTC(lastc, dest);
}
}
- p--;
- while (lastc == '\n') {
+
+ /* Eat all trailing newlines */
+ for (p--; lastc == '\n'; lastc = *--p)
STUNPUTC(dest);
- lastc = *--p;
- }
+
if (in.fd >= 0)
close(in.fd);
if (in.buf)
@@ -426,6 +420,101 @@ expbackq(cmd, quoted, flag)
+STATIC int
+subevalvar(p, str, subtype, startloc, varflags)
+ char *p;
+ char *str;
+ int subtype;
+ int startloc;
+ int varflags;
+{
+
+ char *startp;
+ char *loc = NULL;
+ int c = 0;
+ int saveherefd = herefd;
+ struct nodelist *saveargbackq = argbackq;
+ herefd = -1;
+ argstr(p, 0);
+ STACKSTRNUL(expdest);
+ herefd = saveherefd;
+ argbackq = saveargbackq;
+ startp = stackblock() + startloc;
+
+ switch (subtype) {
+ case VSASSIGN:
+ setvar(str, startp, 0);
+ STADJUST(startp - expdest, expdest);
+ varflags &= ~VSNUL;
+ if (c != 0)
+ *loc = c;
+ return 1;
+
+ case VSQUESTION:
+ if (*p != CTLENDVAR) {
+ outfmt(&errout, "%s\n", startp);
+ error((char *)NULL);
+ }
+ error("%.*s: parameter %snot set", p - str - 1,
+ str, (varflags & VSNUL) ? "null or "
+ : nullstr);
+ return 0;
+
+ case VSTRIMLEFT:
+ for (loc = startp; loc < str - 1; loc++) {
+ c = *loc;
+ *loc = '\0';
+ if (patmatch(str, startp)) {
+ *loc = c;
+ goto recordleft;
+ }
+ *loc = c;
+ }
+ return 0;
+
+ case VSTRIMLEFTMAX:
+ for (loc = str - 1; loc >= startp; loc--) {
+ c = *loc;
+ *loc = '\0';
+ if (patmatch(str, startp)) {
+ *loc = c;
+ goto recordleft;
+ }
+ *loc = c;
+ }
+ return 0;
+
+ case VSTRIMRIGHT:
+ for (loc = str - 1; loc >= startp; loc--) {
+ if (patmatch(str, loc)) {
+ expdest = loc;
+ return 1;
+ }
+ }
+ return 0;
+
+ case VSTRIMRIGHTMAX:
+ for (loc = startp; loc < str - 1; loc++) {
+ if (patmatch(str, loc)) {
+ expdest = loc;
+ return 1;
+ }
+ }
+ return 0;
+
+
+ default:
+ abort();
+ }
+
+recordleft:
+ expdest = (str - 1) - (loc - startp);
+ while (loc != str - 1)
+ *startp++ = *loc++;
+ return 1;
+}
+
+
/*
* Expand a variable, and return a pointer to the next character in the
* input string.
@@ -434,15 +523,19 @@ expbackq(cmd, quoted, flag)
STATIC char *
evalvar(p, flag)
char *p;
- {
+ int flag;
+{
int subtype;
int varflags;
char *var;
char *val;
+ char *pat;
int c;
int set;
int special;
int startloc;
+ int varlen;
+ int easy;
int quotes = flag & (EXP_FULL | EXP_CASE);
varflags = *p++;
@@ -458,60 +551,104 @@ again: /* jump here after setting a variable with ${var=text} */
val = NULL;
} else {
val = lookupvar(var);
- if (val == NULL || (varflags & VSNUL) && val[0] == '\0') {
+ if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
val = NULL;
set = 0;
} else
set = 1;
}
+ varlen = 0;
startloc = expdest - stackblock();
if (set && subtype != VSPLUS) {
/* insert the value of the variable */
if (special) {
+ char *exp, *oexpdest = expdest;
varvalue(*var, varflags & VSQUOTE, flag & EXP_FULL);
+ if (subtype == VSLENGTH) {
+ for (exp = oexpdest;exp != expdest; exp++)
+ varlen++;
+ expdest = oexpdest;
+ }
} else {
- char const *syntax = (varflags & VSQUOTE)? DQSYNTAX : BASESYNTAX;
+ char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
+ : BASESYNTAX;
+
+ if (subtype == VSLENGTH) {
+ for (;*val; val++)
+ varlen++;
+ }
+ else {
+ while (*val) {
+ if (quotes && syntax[*val] == CCTL)
+ STPUTC(CTLESC, expdest);
+ STPUTC(*val++, expdest);
+ }
- while (*val) {
- if (quotes && syntax[*val] == CCTL)
- STPUTC(CTLESC, expdest);
- STPUTC(*val++, expdest);
}
}
}
+
if (subtype == VSPLUS)
set = ! set;
- if (((varflags & VSQUOTE) == 0 || (*var == '@' && shellparam.nparam != 1))
- && (set || subtype == VSNORMAL))
- recordregion(startloc, expdest - stackblock(), varflags & VSQUOTE);
- if (! set && subtype != VSNORMAL) {
- if (subtype == VSPLUS || subtype == VSMINUS) {
+
+ easy = ((varflags & VSQUOTE) == 0 ||
+ (*var == '@' && shellparam.nparam != 1));
+
+
+ switch (subtype) {
+ case VSLENGTH:
+ expdest = cvtnum(varlen, expdest);
+ goto record;
+
+ case VSNORMAL:
+ if (!easy)
+ break;
+record:
+ recordregion(startloc, expdest - stackblock(),
+ varflags & VSQUOTE);
+ break;
+
+ case VSPLUS:
+ case VSMINUS:
+ if (!set) {
argstr(p, flag);
- } else {
- char *startp;
- int saveherefd = herefd;
- struct nodelist *saveargbackq = argbackq;
- herefd = -1;
- argstr(p, 0);
- STACKSTRNUL(expdest);
- herefd = saveherefd;
- argbackq = saveargbackq;
- startp = stackblock() + startloc;
- if (subtype == VSASSIGN) {
- setvar(var, startp, 0);
- STADJUST(startp - expdest, expdest);
- varflags &=~ VSNUL;
+ break;
+ }
+ if (easy)
+ goto record;
+ break;
+
+ case VSTRIMLEFT:
+ case VSTRIMLEFTMAX:
+ case VSTRIMRIGHT:
+ case VSTRIMRIGHTMAX:
+ if (!set)
+ break;
+ /*
+ * Terminate the string and start recording the pattern
+ * right after it
+ */
+ STPUTC('\0', expdest);
+ pat = expdest;
+ if (subevalvar(p, pat, subtype, startloc, varflags))
+ goto record;
+ break;
+
+ case VSASSIGN:
+ case VSQUESTION:
+ if (!set) {
+ if (subevalvar(p, var, subtype, startloc, varflags))
goto again;
- }
- /* subtype == VSQUESTION */
- if (*p != CTLENDVAR) {
- outfmt(&errout, "%s\n", startp);
- error((char *)NULL);
- }
- error("%.*s: parameter %snot set", p - var - 1,
- var, (varflags & VSNUL)? "null or " : nullstr);
+ break;
}
+ if (easy)
+ goto record;
+ break;
+
+ default:
+ abort();
}
+
if (subtype != VSNORMAL) { /* skip to end of alternative */
int nesting = 1;
for (;;) {
@@ -569,12 +706,13 @@ varisset(name)
STATIC void
varvalue(name, quoted, allow_split)
char name;
- {
+ int quoted;
+ int allow_split;
+{
int num;
- char temp[32];
char *p;
int i;
- extern int exitstatus;
+ extern int oexitstatus;
char sep;
char **ap;
char const *syntax;
@@ -599,7 +737,7 @@ varvalue(name, quoted, allow_split)
num = rootpid;
goto numvar;
case '?':
- num = exitstatus;
+ num = oexitstatus;
goto numvar;
case '#':
num = shellparam.nparam;
@@ -607,13 +745,7 @@ varvalue(name, quoted, allow_split)
case '!':
num = backgndpid;
numvar:
- p = temp + 31;
- temp[31] = '\0';
- do {
- *--p = num % 10 + '0';
- } while ((num /= 10) != 0);
- while (*p)
- STPUTC(*p++, expdest);
+ expdest = cvtnum(num, expdest);
break;
case '-':
for (i = 0 ; i < NOPTS ; i++) {
@@ -657,7 +789,11 @@ allargs:
*/
STATIC void
-recordregion(start, end, nulonly) {
+recordregion(start, end, nulonly)
+ int start;
+ int end;
+ int nulonly;
+{
register struct ifsregion *ifsp;
if (ifslastp == NULL) {
@@ -680,7 +816,6 @@ recordregion(start, end, nulonly) {
* strings to the argument list. The regions of the string to be
* searched for IFS characters have been stored by recordregion.
*/
-
STATIC void
ifsbreakup(string, arglist)
char *string;
@@ -692,6 +827,8 @@ ifsbreakup(string, arglist)
register char *p;
char *q;
char *ifs;
+ int ifsspc;
+
start = string;
if (ifslastp != NULL) {
@@ -699,19 +836,20 @@ ifsbreakup(string, arglist)
do {
p = string + ifsp->begoff;
ifs = ifsp->nulonly? nullstr : ifsval();
+ ifsspc = strchr(ifs, ' ') != NULL;
while (p < string + ifsp->endoff) {
q = p;
if (*p == CTLESC)
p++;
if (strchr(ifs, *p++)) {
- if (q > start || *ifs != ' ') {
+ if (q > start || !ifsspc) {
*q = '\0';
sp = (struct strlist *)stalloc(sizeof *sp);
sp->text = start;
*arglist->lastp = sp;
arglist->lastp = &sp->next;
}
- if (*ifs == ' ') {
+ if (ifsspc) {
for (;;) {
if (p >= string + ifsp->endoff)
break;
@@ -728,7 +866,7 @@ ifsbreakup(string, arglist)
}
}
} while ((ifsp = ifsp->next) != NULL);
- if (*start || (*ifs != ' ' && start > string)) {
+ if (*start || (!ifsspc && start > string)) {
sp = (struct strlist *)stalloc(sizeof *sp);
sp->text = start;
*arglist->lastp = sp;
@@ -755,7 +893,8 @@ char *expdir;
STATIC void
expandmeta(str, flag)
struct strlist *str;
- {
+ int flag;
+{
char *p;
struct strlist **savelastp;
struct strlist *sp;
@@ -896,7 +1035,7 @@ expmeta(enddir, name)
*endname++ = '\0';
}
matchdot = 0;
- if (start[0] == '.' || start[0] == CTLESC && start[1] == '.')
+ if (start[0] == '.' || (start[0] == CTLESC && start[1] == '.'))
matchdot++;
while (! int_pending() && (dp = readdir(dirp)) != NULL) {
if (dp->d_name[0] == '.' && ! matchdot)
@@ -907,7 +1046,9 @@ expmeta(enddir, name)
addfname(expdir);
} else {
char *q;
- for (p = enddir, q = dp->d_name ; *p++ = *q++ ;);
+ for (p = enddir, q = dp->d_name;
+ (*p++ = *q++) != '\0';)
+ continue;
p[-1] = '/';
expmeta(p, endname);
}
@@ -962,8 +1103,9 @@ expsort(str)
STATIC struct strlist *
msort(list, len)
struct strlist *list;
- {
- struct strlist *p, *q;
+ int len;
+{
+ struct strlist *p, *q = NULL;
struct strlist **lpp;
int half;
int n;
@@ -1019,6 +1161,7 @@ patmatch(pattern, string)
return pmatch(pattern, string);
}
+
STATIC int
pmatch(pattern, string)
char *pattern;
@@ -1078,6 +1221,8 @@ pmatch(pattern, string)
}
found = 0;
chr = *q++;
+ if (chr == '\0')
+ return 0;
c = *p++;
do {
if (c == CTLESC)
@@ -1164,3 +1309,30 @@ casematch(pattern, val)
popstackmark(&smark);
return result;
}
+
+/*
+ * Our own itoa().
+ */
+
+STATIC char *
+cvtnum(num, buf)
+ int num;
+ char *buf;
+ {
+ char temp[32];
+ int neg = num < 0;
+ char *p = temp + 31;
+
+ temp[31] = '\0';
+
+ do {
+ *--p = num % 10 + '0';
+ } while ((num /= 10) != 0);
+
+ if (neg)
+ *--p = '-';
+
+ while (*p)
+ STPUTC(*p++, buf);
+ return buf;
+}
OpenPOWER on IntegriCloud