svn commit: r293016 - in projects/clang380-import: . bin/sh contrib/binutils/bfd lib/libmd lib/libstand share/man/man4 sys/arm64/arm64 sys/arm64/include sys/boot/forth sys/boot/i386/loader sys/boot...

Dimitry Andric dim at FreeBSD.org
Thu Dec 31 22:55:04 UTC 2015


Author: dim
Date: Thu Dec 31 22:55:02 2015
New Revision: 293016
URL: https://svnweb.freebsd.org/changeset/base/293016

Log:
  Merge ^/head r292951 through r293015.

Added:
  projects/clang380-import/share/man/man4/rtwn.4
     - copied unchanged from r293015, head/share/man/man4/rtwn.4
  projects/clang380-import/share/man/man4/rtwnfw.4
     - copied unchanged from r293015, head/share/man/man4/rtwnfw.4
  projects/clang380-import/sys/contrib/dev/rtwn/
     - copied from r293015, head/sys/contrib/dev/rtwn/
  projects/clang380-import/sys/dev/rtwn/
     - copied from r293015, head/sys/dev/rtwn/
  projects/clang380-import/sys/modules/rtwnfw/
     - copied from r293015, head/sys/modules/rtwnfw/
  projects/clang380-import/sys/opencrypto/xform_aes_icm.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_aes_icm.c
  projects/clang380-import/sys/opencrypto/xform_aes_xts.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_aes_xts.c
  projects/clang380-import/sys/opencrypto/xform_auth.h
     - copied unchanged from r293015, head/sys/opencrypto/xform_auth.h
  projects/clang380-import/sys/opencrypto/xform_blf.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_blf.c
  projects/clang380-import/sys/opencrypto/xform_cast5.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_cast5.c
  projects/clang380-import/sys/opencrypto/xform_cml.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_cml.c
  projects/clang380-import/sys/opencrypto/xform_comp.h
     - copied unchanged from r293015, head/sys/opencrypto/xform_comp.h
  projects/clang380-import/sys/opencrypto/xform_deflate.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_deflate.c
  projects/clang380-import/sys/opencrypto/xform_des1.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_des1.c
  projects/clang380-import/sys/opencrypto/xform_des3.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_des3.c
  projects/clang380-import/sys/opencrypto/xform_enc.h
     - copied unchanged from r293015, head/sys/opencrypto/xform_enc.h
  projects/clang380-import/sys/opencrypto/xform_gmac.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_gmac.c
  projects/clang380-import/sys/opencrypto/xform_md5.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_md5.c
  projects/clang380-import/sys/opencrypto/xform_null.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_null.c
  projects/clang380-import/sys/opencrypto/xform_rijndael.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_rijndael.c
  projects/clang380-import/sys/opencrypto/xform_rmd160.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_rmd160.c
  projects/clang380-import/sys/opencrypto/xform_sha1.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_sha1.c
  projects/clang380-import/sys/opencrypto/xform_sha2.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_sha2.c
  projects/clang380-import/sys/opencrypto/xform_skipjack.c
     - copied unchanged from r293015, head/sys/opencrypto/xform_skipjack.c
  projects/clang380-import/sys/opencrypto/xform_userland.h
     - copied unchanged from r293015, head/sys/opencrypto/xform_userland.h
Modified:
  projects/clang380-import/COPYRIGHT
  projects/clang380-import/bin/sh/expand.c
  projects/clang380-import/bin/sh/expand.h
  projects/clang380-import/contrib/binutils/bfd/elf32-arm.c
  projects/clang380-import/lib/libmd/mdXhl.c
  projects/clang380-import/lib/libstand/Makefile
  projects/clang380-import/share/man/man4/Makefile
  projects/clang380-import/sys/arm64/arm64/identcpu.c
  projects/clang380-import/sys/arm64/arm64/mp_machdep.c
  projects/clang380-import/sys/arm64/include/armreg.h
  projects/clang380-import/sys/arm64/include/cpu.h
  projects/clang380-import/sys/boot/forth/loader.conf
  projects/clang380-import/sys/boot/forth/menu-commands.4th
  projects/clang380-import/sys/boot/forth/menu.rc
  projects/clang380-import/sys/boot/forth/support.4th
  projects/clang380-import/sys/boot/i386/loader/main.c
  projects/clang380-import/sys/boot/zfs/libzfs.h
  projects/clang380-import/sys/boot/zfs/zfs.c
  projects/clang380-import/sys/boot/zfs/zfsimpl.c
  projects/clang380-import/sys/compat/linuxkpi/common/include/linux/cdev.h
  projects/clang380-import/sys/compat/linuxkpi/common/include/linux/device.h
  projects/clang380-import/sys/compat/linuxkpi/common/include/linux/file.h
  projects/clang380-import/sys/compat/linuxkpi/common/include/linux/kobject.h
  projects/clang380-import/sys/compat/linuxkpi/common/include/linux/miscdevice.h
  projects/clang380-import/sys/compat/linuxkpi/common/src/linux_compat.c
  projects/clang380-import/sys/compat/linuxkpi/common/src/linux_pci.c
  projects/clang380-import/sys/conf/newvers.sh
  projects/clang380-import/sys/crypto/sha1.h
  projects/clang380-import/sys/dev/cxgb/ulp/tom/cxgb_l2t.c
  projects/clang380-import/sys/dev/cxgbe/tom/t4_tom_l2t.c
  projects/clang380-import/sys/dev/usb/net/if_axe.c
  projects/clang380-import/sys/dev/usb/usbdevs
  projects/clang380-import/sys/fs/nullfs/null_vnops.c
  projects/clang380-import/sys/modules/Makefile
  projects/clang380-import/sys/net/bpf.c
  projects/clang380-import/sys/net/flowtable.c
  projects/clang380-import/sys/net/if.c
  projects/clang380-import/sys/net/if_ethersubr.c
  projects/clang380-import/sys/net/if_gif.c
  projects/clang380-import/sys/net/if_gre.c
  projects/clang380-import/sys/net/if_llatbl.c
  projects/clang380-import/sys/net/if_llatbl.h
  projects/clang380-import/sys/net/if_var.h
  projects/clang380-import/sys/net/route.h
  projects/clang380-import/sys/netinet/if_ether.c
  projects/clang380-import/sys/netinet/if_ether.h
  projects/clang380-import/sys/netinet/in.c
  projects/clang380-import/sys/netinet/ip_output.c
  projects/clang380-import/sys/netinet/toecore.c
  projects/clang380-import/sys/netinet6/icmp6.c
  projects/clang380-import/sys/netinet6/in6.c
  projects/clang380-import/sys/netinet6/in6.h
  projects/clang380-import/sys/netinet6/ip6_output.c
  projects/clang380-import/sys/netinet6/nd6.c
  projects/clang380-import/sys/netinet6/nd6.h
  projects/clang380-import/sys/netinet6/nd6_nbr.c
  projects/clang380-import/sys/ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c
  projects/clang380-import/sys/opencrypto/skipjack.h
  projects/clang380-import/sys/opencrypto/xform.c
  projects/clang380-import/sys/opencrypto/xform.h
  projects/clang380-import/sys/sparc64/include/ktr.h
  projects/clang380-import/sys/sys/copyright.h
  projects/clang380-import/sys/sys/param.h
  projects/clang380-import/sys/xen/xenbus/xenbusb.c
  projects/clang380-import/tests/sys/kern/unix_passfd_test.c
  projects/clang380-import/usr.sbin/bhyve/bhyverun.c
  projects/clang380-import/usr.sbin/bhyve/pci_emul.c
  projects/clang380-import/usr.sbin/camdd/camdd.c
Directory Properties:
  projects/clang380-import/   (props changed)
  projects/clang380-import/contrib/binutils/   (props changed)
  projects/clang380-import/contrib/pf/   (props changed)
  projects/clang380-import/share/   (props changed)
  projects/clang380-import/share/man/man4/   (props changed)
  projects/clang380-import/sys/   (props changed)
  projects/clang380-import/sys/boot/   (props changed)
  projects/clang380-import/sys/conf/   (props changed)
  projects/clang380-import/usr.sbin/bhyve/   (props changed)

Modified: projects/clang380-import/COPYRIGHT
==============================================================================
--- projects/clang380-import/COPYRIGHT	Thu Dec 31 22:52:11 2015	(r293015)
+++ projects/clang380-import/COPYRIGHT	Thu Dec 31 22:55:02 2015	(r293016)
@@ -4,7 +4,7 @@
 The compilation of software known as FreeBSD is distributed under the
 following terms:
 
-Copyright (c) 1992-2015 The FreeBSD Project. All rights reserved.
+Copyright (c) 1992-2016 The FreeBSD Project. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions

Modified: projects/clang380-import/bin/sh/expand.c
==============================================================================
--- projects/clang380-import/bin/sh/expand.c	Thu Dec 31 22:52:11 2015	(r293015)
+++ projects/clang380-import/bin/sh/expand.c	Thu Dec 31 22:55:02 2015	(r293016)
@@ -3,6 +3,8 @@
  *	The Regents of the University of California.  All rights reserved.
  * Copyright (c) 1997-2005
  *	Herbert Xu <herbert at gondor.apana.org.au>.  All rights reserved.
+ * Copyright (c) 2010-2015
+ *	Jilles Tjoelker <jilles at stack.nl>.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Kenneth Almquist.
@@ -79,42 +81,32 @@ __FBSDID("$FreeBSD$");
 #include "show.h"
 #include "builtins.h"
 
-/*
- * Structure specifying which parts of the string should be searched
- * for IFS characters.
- */
+enum wordstate { WORD_IDLE, WORD_WS_DELIMITED, WORD_QUOTEMARK };
 
-struct ifsregion {
-	struct ifsregion *next;	/* next region in list */
-	int begoff;		/* offset of start of region */
-	int endoff;		/* offset of end of region */
-	int inquotes;		/* search for nul bytes only */
+struct worddest {
+	struct arglist *list;
+	enum wordstate state;
 };
 
-
 static char *expdest;			/* output of current string */
 static struct nodelist *argbackq;	/* list of back quote expressions */
-static struct ifsregion ifsfirst;	/* first struct in list of ifs regions */
-static struct ifsregion *ifslastp;	/* last struct in list */
 
-static char *argstr(char *, int);
+static char *argstr(char *, int, struct worddest *);
 static char *exptilde(char *, int);
-static char *expari(char *);
-static void expbackq(union node *, int, int);
-static int subevalvar_trim(char *, int, int, int, int);
+static char *expari(char *, int, struct worddest *);
+static void expbackq(union node *, int, int, struct worddest *);
+static void subevalvar_trim(char *, int, int, int);
 static int subevalvar_misc(char *, const char *, int, int, int);
-static char *evalvar(char *, int);
+static char *evalvar(char *, int, struct worddest *);
 static int varisset(const char *, int);
-static void strtodest(const char *, int, int, int);
-static void varvalue(const char *, int, int, int);
-static void recordregion(int, int, int);
-static void removerecordregions(int);
-static void ifsbreakup(char *, struct arglist *);
-static void expandmeta(struct arglist *, struct arglist *);
+static void strtodest(const char *, int, int, int, struct worddest *);
+static void reprocess(int, int, int, int, struct worddest *);
+static void varvalue(const char *, int, int, int, struct worddest *);
+static void expandmeta(char *, struct arglist *);
 static void expmeta(char *, char *, struct arglist *);
 static int expsortcmp(const void *, const void *);
-static int patmatch(const char *, const char *, int);
-static char *cvtnum(int, char *);
+static int patmatch(const char *, const char *);
+static void cvtnum(int, char *);
 static int collate_range_cmp(wchar_t, wchar_t);
 
 void
@@ -169,6 +161,53 @@ stputs_quotes(const char *data, const ch
 }
 #define STPUTS_QUOTES(data, syntax, p) p = stputs_quotes((data), syntax, p)
 
+static char *
+nextword(char c, int flag, char *p, struct worddest *dst)
+{
+	int is_ws;
+
+	is_ws = c == '\t' || c == '\n' || c == ' ';
+	if (p != stackblock() || (is_ws ? dst->state == WORD_QUOTEMARK :
+	    dst->state != WORD_WS_DELIMITED) || c == '\0') {
+		STPUTC('\0', p);
+		if (flag & EXP_GLOB)
+			expandmeta(grabstackstr(p), dst->list);
+		else
+			appendarglist(dst->list, grabstackstr(p));
+		dst->state = is_ws ? WORD_WS_DELIMITED : WORD_IDLE;
+	} else if (!is_ws && dst->state == WORD_WS_DELIMITED)
+		dst->state = WORD_IDLE;
+	/* Reserve space while the stack string is empty. */
+	appendarglist(dst->list, NULL);
+	dst->list->count--;
+	STARTSTACKSTR(p);
+	return p;
+}
+#define NEXTWORD(c, flag, p, dstlist) p = nextword(c, flag, p, dstlist)
+
+static char *
+stputs_split(const char *data, const char *syntax, int flag, char *p,
+    struct worddest *dst)
+{
+	const char *ifs;
+	char c;
+
+	ifs = ifsset() ? ifsval() : " \t\n";
+	while (*data) {
+		CHECKSTRSPACE(2, p);
+		c = *data++;
+		if (strchr(ifs, c) != NULL) {
+			NEXTWORD(c, flag, p, dst);
+			continue;
+		}
+		if (flag & EXP_GLOB && syntax[(int)c] == CCTL)
+			USTPUTC(CTLESC, p);
+		USTPUTC(c, p);
+	}
+	return (p);
+}
+#define STPUTS_SPLIT(data, syntax, flag, p, dst) p = stputs_split((data), syntax, flag, p, dst)
+
 /*
  * Perform expansions on an argument, placing the resulting list of arguments
  * in arglist.  Parameter expansion, command substitution and arithmetic
@@ -184,34 +223,31 @@ stputs_quotes(const char *data, const ch
 void
 expandarg(union node *arg, struct arglist *arglist, int flag)
 {
-	struct arglist exparg;
-	char *p;
+	struct worddest exparg;
 
+	if (fflag)
+		flag &= ~EXP_GLOB;
 	argbackq = arg->narg.backquote;
+	exparg.list = arglist;
+	exparg.state = WORD_IDLE;
 	STARTSTACKSTR(expdest);
-	ifsfirst.next = NULL;
-	ifslastp = NULL;
-	argstr(arg->narg.text, flag);
+	argstr(arg->narg.text, flag, &exparg);
 	if (arglist == NULL) {
 		STACKSTRNUL(expdest);
 		return;			/* here document expanded */
 	}
-	STPUTC('\0', expdest);
-	p = grabstackstr(expdest);
-	emptyarglist(&exparg);
-	if (flag & EXP_FULL) {
-		ifsbreakup(p, &exparg);
-		expandmeta(&exparg, arglist);
-	} else
-		appendarglist(arglist, p);
-	while (ifsfirst.next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifsfirst.next->next;
-		ckfree(ifsfirst.next);
-		ifsfirst.next = ifsp;
-		INTON;
+	if ((flag & EXP_SPLIT) == 0 || expdest != stackblock() ||
+	    exparg.state == WORD_QUOTEMARK) {
+		STPUTC('\0', expdest);
+		if (flag & EXP_SPLIT) {
+			if (flag & EXP_GLOB)
+				expandmeta(grabstackstr(expdest), exparg.list);
+			else
+				appendarglist(exparg.list, grabstackstr(expdest));
+		}
 	}
+	if ((flag & EXP_SPLIT) == 0)
+		appendarglist(arglist, grabstackstr(expdest));
 }
 
 
@@ -221,15 +257,16 @@ expandarg(union node *arg, struct arglis
  * expansion, and tilde expansion if requested via EXP_TILDE/EXP_VARTILDE.
  * Processing ends at a CTLENDVAR or CTLENDARI character as well as '\0'.
  * This is used to expand word in ${var+word} etc.
- * If EXP_FULL or EXP_CASE are set, keep and/or generate CTLESC
+ * If EXP_GLOB or EXP_CASE are set, keep and/or generate CTLESC
  * characters to allow for further processing.
- * If EXP_FULL is set, also preserve CTLQUOTEMARK characters.
+ *
+ * If EXP_SPLIT is set, dst receives any complete words produced.
  */
 static char *
-argstr(char *p, int flag)
+argstr(char *p, int flag, struct worddest *dst)
 {
 	char c;
-	int quotes = flag & (EXP_FULL | EXP_CASE);	/* do CTLESC */
+	int quotes = flag & (EXP_GLOB | EXP_CASE);	/* do CTLESC */
 	int firsteq = 1;
 	int split_lit;
 	int lit_quoted;
@@ -253,32 +290,33 @@ argstr(char *p, int flag)
 			if (p[0] == CTLVAR && (p[1] & VSQUOTE) != 0 &&
 			    p[2] == '@' && p[3] == '=')
 				break;
-			if ((flag & EXP_FULL) != 0)
-				USTPUTC(c, expdest);
+			if ((flag & EXP_SPLIT) != 0 && expdest == stackblock())
+				dst->state = WORD_QUOTEMARK;
 			break;
 		case CTLQUOTEEND:
 			lit_quoted = 0;
 			break;
 		case CTLESC:
-			if (quotes)
-				USTPUTC(c, expdest);
 			c = *p++;
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
+			if (quotes)
+				USTPUTC(CTLESC, expdest);
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() -
-				    (quotes ? 2 : 1),
-				    expdest - stackblock(), 0);
 			break;
 		case CTLVAR:
-			p = evalvar(p, flag);
+			p = evalvar(p, flag, dst);
 			break;
 		case CTLBACKQ:
 		case CTLBACKQ|CTLQUOTE:
-			expbackq(argbackq->n, c & CTLQUOTE, flag);
+			expbackq(argbackq->n, c & CTLQUOTE, flag, dst);
 			argbackq = argbackq->next;
 			break;
 		case CTLARI:
-			p = expari(p);
+			p = expari(p, flag, dst);
 			break;
 		case ':':
 		case '=':
@@ -286,10 +324,12 @@ argstr(char *p, int flag)
 			 * sort of a hack - expand tildes in variable
 			 * assignments (after the first '=' and after ':'s).
 			 */
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() - 1,
-				    expdest - stackblock(), 0);
 			if (flag & EXP_VARTILDE && *p == '~' &&
 			    (c != '=' || firsteq)) {
 				if (c == '=')
@@ -298,10 +338,12 @@ argstr(char *p, int flag)
 			}
 			break;
 		default:
+			if (split_lit && !lit_quoted &&
+			    strchr(ifsset() ? ifsval() : " \t\n", c) != NULL) {
+				NEXTWORD(c, flag, expdest, dst);
+				break;
+			}
 			USTPUTC(c, expdest);
-			if (split_lit && !lit_quoted)
-				recordregion(expdest - stackblock() - 1,
-				    expdest - stackblock(), 0);
 		}
 	}
 }
@@ -345,7 +387,7 @@ exptilde(char *p, int flag)
 			*p = c;
 			if (home == NULL || *home == '\0')
 				return (startp);
-			strtodest(home, flag, VSNORMAL, 1);
+			strtodest(home, flag, VSNORMAL, 1, NULL);
 			return (p);
 		}
 		p++;
@@ -353,51 +395,11 @@ exptilde(char *p, int flag)
 }
 
 
-static void
-removerecordregions(int endoff)
-{
-	if (ifslastp == NULL)
-		return;
-
-	if (ifsfirst.endoff > endoff) {
-		while (ifsfirst.next != NULL) {
-			struct ifsregion *ifsp;
-			INTOFF;
-			ifsp = ifsfirst.next->next;
-			ckfree(ifsfirst.next);
-			ifsfirst.next = ifsp;
-			INTON;
-		}
-		if (ifsfirst.begoff > endoff)
-			ifslastp = NULL;
-		else {
-			ifslastp = &ifsfirst;
-			ifsfirst.endoff = endoff;
-		}
-		return;
-	}
-
-	ifslastp = &ifsfirst;
-	while (ifslastp->next && ifslastp->next->begoff < endoff)
-		ifslastp=ifslastp->next;
-	while (ifslastp->next != NULL) {
-		struct ifsregion *ifsp;
-		INTOFF;
-		ifsp = ifslastp->next->next;
-		ckfree(ifslastp->next);
-		ifslastp->next = ifsp;
-		INTON;
-	}
-	if (ifslastp->endoff > endoff)
-		ifslastp->endoff = endoff;
-}
-
 /*
  * Expand arithmetic expression.
- * Note that flag is not required as digits never require CTLESC characters.
  */
 static char *
-expari(char *p)
+expari(char *p, int flag, struct worddest *dst)
 {
 	char *q, *start;
 	arith_t result;
@@ -407,8 +409,7 @@ expari(char *p)
 
 	quoted = *p++ == '"';
 	begoff = expdest - stackblock();
-	p = argstr(p, 0);
-	removerecordregions(begoff);
+	p = argstr(p, 0, NULL);
 	STPUTC('\0', expdest);
 	start = stackblock() + begoff;
 
@@ -425,7 +426,7 @@ expari(char *p)
 	adj = strlen(expdest);
 	STADJUST(adj, expdest);
 	if (!quoted)
-		recordregion(begoff, expdest - stackblock(), 0);
+		reprocess(expdest - adj - stackblock(), flag, VSNORMAL, 0, dst);
 	return p;
 }
 
@@ -434,35 +435,34 @@ expari(char *p)
  * Perform command substitution.
  */
 static void
-expbackq(union node *cmd, int quoted, int flag)
+expbackq(union node *cmd, int quoted, int flag, struct worddest *dst)
 {
 	struct backcmd in;
 	int i;
 	char buf[128];
 	char *p;
 	char *dest = expdest;
-	struct ifsregion saveifs, *savelastp;
 	struct nodelist *saveargbackq;
 	char lastc;
-	int startloc = dest - stackblock();
 	char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
+	int quotes = flag & (EXP_GLOB | EXP_CASE);
 	size_t nnl;
+	const char *ifs;
 
 	INTOFF;
-	saveifs = ifsfirst;
-	savelastp = ifslastp;
 	saveargbackq = argbackq;
 	p = grabstackstr(dest);
 	evalbackcmd(cmd, &in);
 	ungrabstackstr(p, dest);
-	ifsfirst = saveifs;
-	ifslastp = savelastp;
 	argbackq = saveargbackq;
 
 	p = in.buf;
 	lastc = '\0';
 	nnl = 0;
+	if (!quoted && flag & EXP_SPLIT)
+		ifs = ifsset() ? ifsval() : " \t\n";
+	else
+		ifs = "";
 	/* Don't copy trailing newlines */
 	for (;;) {
 		if (--in.nleft < 0) {
@@ -476,15 +476,27 @@ expbackq(union node *cmd, int quoted, in
 			in.nleft = i - 1;
 		}
 		lastc = *p++;
-		if (lastc != '\0') {
-			if (lastc == '\n') {
-				nnl++;
-			} else {
-				CHECKSTRSPACE(nnl + 2, dest);
-				while (nnl > 0) {
-					nnl--;
-					USTPUTC('\n', dest);
+		if (lastc == '\0')
+			continue;
+		if (lastc == '\n') {
+			nnl++;
+		} else {
+			if (nnl > 0) {
+				if (strchr(ifs, '\n') != NULL) {
+					NEXTWORD('\n', flag, dest, dst);
+					nnl = 0;
+				} else {
+					CHECKSTRSPACE(nnl + 2, dest);
+					while (nnl > 0) {
+						nnl--;
+						USTPUTC('\n', dest);
+					}
 				}
+			}
+			if (strchr(ifs, lastc) != NULL)
+				NEXTWORD(lastc, flag, dest, dst);
+			else {
+				CHECKSTRSPACE(2, dest);
 				if (quotes && syntax[(int)lastc] == CCTL)
 					USTPUTC(CTLESC, dest);
 				USTPUTC(lastc, dest);
@@ -498,8 +510,6 @@ expbackq(union node *cmd, int quoted, in
 		ckfree(in.buf);
 	if (in.jp)
 		exitstatus = waitforjob(in.jp, (int *)NULL);
-	if (quoted == 0)
-		recordregion(startloc, dest - stackblock(), 0);
 	TRACE(("expbackq: size=%td: \"%.*s\"\n",
 		((dest - stackblock()) - startloc),
 		(int)((dest - stackblock()) - startloc),
@@ -521,18 +531,17 @@ recordleft(const char *str, const char *
 		*startp++ = *loc++;
 }
 
-static int
-subevalvar_trim(char *p, int strloc, int subtype, int startloc, int quotes)
+static void
+subevalvar_trim(char *p, int strloc, int subtype, int startloc)
 {
 	char *startp;
 	char *loc = NULL;
-	char *q;
 	char *str;
 	int c = 0;
 	struct nodelist *saveargbackq = argbackq;
 	int amount;
 
-	argstr(p, EXP_CASE | EXP_TILDE);
+	argstr(p, EXP_CASE | EXP_TILDE, NULL);
 	STACKSTRNUL(expdest);
 	argbackq = saveargbackq;
 	startp = stackblock() + startloc;
@@ -543,72 +552,56 @@ subevalvar_trim(char *p, int strloc, int
 		for (loc = startp; loc < str; loc++) {
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, quotes)) {
+			if (patmatch(str, startp)) {
 				*loc = c;
 				recordleft(str, loc, startp);
-				return 1;
+				return;
 			}
 			*loc = c;
-			if (quotes && *loc == CTLESC)
-				loc++;
 		}
-		return 0;
+		break;
 
 	case VSTRIMLEFTMAX:
 		for (loc = str - 1; loc >= startp;) {
 			c = *loc;
 			*loc = '\0';
-			if (patmatch(str, startp, quotes)) {
+			if (patmatch(str, startp)) {
 				*loc = c;
 				recordleft(str, loc, startp);
-				return 1;
+				return;
 			}
 			*loc = c;
 			loc--;
-			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
 		}
-		return 0;
+		break;
 
 	case VSTRIMRIGHT:
 		for (loc = str - 1; loc >= startp;) {
-			if (patmatch(str, loc, quotes)) {
+			if (patmatch(str, loc)) {
 				amount = loc - expdest;
 				STADJUST(amount, expdest);
-				return 1;
+				return;
 			}
 			loc--;
-			if (quotes && loc > startp && *(loc - 1) == CTLESC) {
-				for (q = startp; q < loc; q++)
-					if (*q == CTLESC)
-						q++;
-				if (q > loc)
-					loc--;
-			}
 		}
-		return 0;
+		break;
 
 	case VSTRIMRIGHTMAX:
 		for (loc = startp; loc < str - 1; loc++) {
-			if (patmatch(str, loc, quotes)) {
+			if (patmatch(str, loc)) {
 				amount = loc - expdest;
 				STADJUST(amount, expdest);
-				return 1;
+				return;
 			}
-			if (quotes && *loc == CTLESC)
-				loc++;
 		}
-		return 0;
+		break;
 
 
 	default:
 		abort();
 	}
+	amount = (expdest - stackblock() - strloc) + 1;
+	STADJUST(-amount, expdest);
 }
 
 
@@ -620,7 +613,7 @@ subevalvar_misc(char *p, const char *var
 	struct nodelist *saveargbackq = argbackq;
 	int amount;
 
-	argstr(p, EXP_TILDE);
+	argstr(p, EXP_TILDE, NULL);
 	STACKSTRNUL(expdest);
 	argbackq = saveargbackq;
 	startp = stackblock() + startloc;
@@ -653,7 +646,7 @@ subevalvar_misc(char *p, const char *var
  */
 
 static char *
-evalvar(char *p, int flag)
+evalvar(char *p, int flag, struct worddest *dst)
 {
 	int subtype;
 	int varflags;
@@ -666,9 +659,7 @@ evalvar(char *p, int flag)
 	int startloc;
 	int varlen;
 	int varlenb;
-	int easy;
-	int quotes = flag & (EXP_FULL | EXP_CASE);
-	int record = 0;
+	char buf[21];
 
 	varflags = (unsigned char)*p++;
 	subtype = varflags & VSTYPE;
@@ -710,10 +701,16 @@ again: /* jump here after setting a vari
 	if (set && subtype != VSPLUS) {
 		/* insert the value of the variable */
 		if (special) {
-			if (varflags & VSLINENO)
-				STPUTBIN(var, p - var - 1, expdest);
-			else
-				varvalue(var, varflags & VSQUOTE, subtype, flag);
+			if (varflags & VSLINENO) {
+				if (p - var > (ptrdiff_t)sizeof(buf))
+					abort();
+				memcpy(buf, var, p - var - 1);
+				buf[p - var - 1] = '\0';
+				strtodest(buf, flag, subtype,
+				    varflags & VSQUOTE, dst);
+			} else
+				varvalue(var, varflags & VSQUOTE, subtype, flag,
+				    dst);
 			if (subtype == VSLENGTH) {
 				varlenb = expdest - stackblock() - startloc;
 				varlen = varlenb;
@@ -734,35 +731,29 @@ again: /* jump here after setting a vari
 			}
 			else
 				strtodest(val, flag, subtype,
-				    varflags & VSQUOTE);
+				    varflags & VSQUOTE, dst);
 		}
 	}
 
 	if (subtype == VSPLUS)
 		set = ! set;
 
-	easy = ((varflags & VSQUOTE) == 0 ||
-		(*var == '@' && shellparam.nparam != 1));
-
-
 	switch (subtype) {
 	case VSLENGTH:
-		expdest = cvtnum(varlen, expdest);
-		record = 1;
+		cvtnum(varlen, buf);
+		strtodest(buf, flag, VSNORMAL, varflags & VSQUOTE, dst);
 		break;
 
 	case VSNORMAL:
-		record = easy;
 		break;
 
 	case VSPLUS:
 	case VSMINUS:
 		if (!set) {
-			argstr(p, flag | (flag & EXP_FULL ? EXP_SPLIT_LIT : 0) |
-			    (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0));
+			argstr(p, flag | (flag & EXP_SPLIT ? EXP_SPLIT_LIT : 0) |
+			    (varflags & VSQUOTE ? EXP_LIT_QUOTED : 0), dst);
 			break;
 		}
-		record = easy;
 		break;
 
 	case VSTRIMLEFT:
@@ -777,14 +768,10 @@ again: /* jump here after setting a vari
 		 */
 		STPUTC('\0', expdest);
 		patloc = expdest - stackblock();
-		if (subevalvar_trim(p, patloc, subtype,
-		    startloc, quotes) == 0) {
-			int amount = (expdest - stackblock() - patloc) + 1;
-			STADJUST(-amount, expdest);
-		}
-		/* Remove any recorded regions beyond start of variable */
-		removerecordregions(startloc);
-		record = 1;
+		subevalvar_trim(p, patloc, subtype, startloc);
+		reprocess(startloc, flag, VSNORMAL, varflags & VSQUOTE, dst);
+		if (flag & EXP_SPLIT && *var == '@' && varflags & VSQUOTE)
+			dst->state = WORD_QUOTEMARK;
 		break;
 
 	case VSASSIGN:
@@ -793,16 +780,10 @@ again: /* jump here after setting a vari
 			if (subevalvar_misc(p, var, subtype, startloc,
 			    varflags)) {
 				varflags &= ~VSNUL;
-				/*
-				 * Remove any recorded regions beyond
-				 * start of variable
-				 */
-				removerecordregions(startloc);
 				goto again;
 			}
 			break;
 		}
-		record = easy;
 		break;
 
 	case VSERROR:
@@ -814,11 +795,6 @@ again: /* jump here after setting a vari
 		abort();
 	}
 
-	if (record)
-		recordregion(startloc, expdest - stackblock(),
-		    varflags & VSQUOTE || (ifsset() && ifsval()[0] == '\0' &&
-		    (*var == '@' || *var == '*')));
-
 	if (subtype != VSNORMAL) {	/* skip to end of alternative */
 		int nesting = 1;
 		for (;;) {
@@ -884,26 +860,80 @@ varisset(const char *name, int nulok)
 }
 
 static void
-strtodest(const char *p, int flag, int subtype, int quoted)
+strtodest(const char *p, int flag, int subtype, int quoted,
+    struct worddest *dst)
 {
-	if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH)
+	if (subtype == VSLENGTH || subtype == VSTRIMLEFT ||
+	    subtype == VSTRIMLEFTMAX || subtype == VSTRIMRIGHT ||
+	    subtype == VSTRIMRIGHTMAX)
+		STPUTS(p, expdest);
+	else if (flag & EXP_SPLIT && !quoted && dst != NULL)
+		STPUTS_SPLIT(p, BASESYNTAX, flag, expdest, dst);
+	else if (flag & (EXP_GLOB | EXP_CASE))
 		STPUTS_QUOTES(p, quoted ? DQSYNTAX : BASESYNTAX, expdest);
 	else
 		STPUTS(p, expdest);
 }
 
+static void
+reprocess(int startloc, int flag, int subtype, int quoted,
+    struct worddest *dst)
+{
+	static char *buf = NULL;
+	static size_t buflen = 0;
+	char *startp;
+	size_t len, zpos, zlen;
+
+	startp = stackblock() + startloc;
+	len = expdest - startp;
+	if (len >= SIZE_MAX / 2)
+		abort();
+	INTOFF;
+	if (len >= buflen) {
+		ckfree(buf);
+		buf = NULL;
+	}
+	if (buflen < 128)
+		buflen = 128;
+	while (len >= buflen)
+		buflen <<= 1;
+	if (buf == NULL)
+		buf = ckmalloc(buflen);
+	INTON;
+	memcpy(buf, startp, len);
+	buf[len] = '\0';
+	STADJUST(-len, expdest);
+	for (zpos = 0;;) {
+		zlen = strlen(buf + zpos);
+		strtodest(buf + zpos, flag, subtype, quoted, dst);
+		zpos += zlen + 1;
+		if (zpos == len + 1)
+			break;
+		if (flag & EXP_SPLIT && (quoted || (zlen > 0 && zpos < len)))
+			NEXTWORD('\0', flag, expdest, dst);
+	}
+}
+
 /*
  * Add the value of a specialized variable to the stack string.
  */
 
 static void
-varvalue(const char *name, int quoted, int subtype, int flag)
+varvalue(const char *name, int quoted, int subtype, int flag,
+    struct worddest *dst)
 {
 	int num;
 	char *p;
 	int i;
+	int splitlater;
 	char sep[2];
 	char **ap;
+	char buf[(NSHORTOPTS > 10 ? NSHORTOPTS : 10) + 1];
+
+	if (subtype == VSLENGTH)
+		flag &= ~EXP_FULL;
+	splitlater = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX ||
+		subtype == VSTRIMRIGHT || subtype == VSTRIMRIGHTMAX;
 
 	switch (*name) {
 	case '$':
@@ -919,18 +949,28 @@ varvalue(const char *name, int quoted, i
 		num = backgndpidval();
 		break;
 	case '-':
+		p = buf;
 		for (i = 0 ; i < NSHORTOPTS ; i++) {
 			if (optlist[i].val)
-				STPUTC(optlist[i].letter, expdest);
+				*p++ = optlist[i].letter;
 		}
+		*p = '\0';
+		strtodest(buf, flag, subtype, quoted, dst);
 		return;
 	case '@':
-		if (flag & EXP_FULL && quoted) {
+		if (flag & EXP_SPLIT && quoted) {
 			for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-				strtodest(p, flag, subtype, quoted);
-				if (*ap)
-					STPUTC('\0', expdest);
+				strtodest(p, flag, subtype, quoted, dst);
+				if (*ap) {
+					if (splitlater)
+						STPUTC('\0', expdest);
+					else
+						NEXTWORD('\0', flag, expdest,
+						    dst);
+				}
 			}
+			if (shellparam.nparam > 0)
+				dst->state = WORD_QUOTEMARK;
 			return;
 		}
 		/* FALLTHROUGH */
@@ -941,13 +981,17 @@ varvalue(const char *name, int quoted, i
 			sep[0] = ' ';
 		sep[1] = '\0';
 		for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
-			strtodest(p, flag, subtype, quoted);
+			strtodest(p, flag, subtype, quoted, dst);
 			if (!*ap)
 				break;
 			if (sep[0])
-				strtodest(sep, flag, subtype, quoted);
-			else if (flag & EXP_FULL && !quoted && **ap != '\0')
-				STPUTC('\0', expdest);
+				strtodest(sep, flag, subtype, quoted, dst);
+			else if (flag & EXP_SPLIT && !quoted && **ap != '\0') {
+				if (splitlater)
+					STPUTC('\0', expdest);
+				else
+					NEXTWORD('\0', flag, expdest, dst);
+			}
 		}
 		return;
 	default:
@@ -959,192 +1003,53 @@ varvalue(const char *name, int quoted, i
 				p = shellparam.p[num - 1];
 			else
 				return;
-			strtodest(p, flag, subtype, quoted);
+			strtodest(p, flag, subtype, quoted, dst);
 		}
 		return;
 	}
-	expdest = cvtnum(num, expdest);
-}
-
-
-
-/*
- * Record the fact that we have to scan this region of the
- * string for IFS characters.
- */
-
-static void
-recordregion(int start, int end, int inquotes)
-{
-	struct ifsregion *ifsp;
-
-	INTOFF;
-	if (ifslastp == NULL) {
-		ifsp = &ifsfirst;
-	} else {
-		if (ifslastp->endoff == start
-		    && ifslastp->inquotes == inquotes) {
-			/* extend previous area */
-			ifslastp->endoff = end;
-			INTON;
-			return;
-		}
-		ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
-		ifslastp->next = ifsp;
-	}
-	ifslastp = ifsp;
-	ifslastp->next = NULL;
-	ifslastp->begoff = start;
-	ifslastp->endoff = end;
-	ifslastp->inquotes = inquotes;
-	INTON;
+	cvtnum(num, buf);
+	strtodest(buf, flag, subtype, quoted, dst);
 }
 
 
 
-/*
- * Break the argument string into pieces based upon IFS and add the
- * strings to the argument list.  The regions of the string to be
- * searched for IFS characters have been stored by recordregion.
- * CTLESC characters are preserved but have little effect in this pass
- * other than escaping CTL* characters.  In particular, they do not escape
- * IFS characters: that should be done with the ifsregion mechanism.
- * CTLQUOTEMARK characters are used to preserve empty quoted strings.
- * This pass treats them as a regular character, making the string non-empty.
- * Later, they are removed along with the other CTL* characters.
- */
-static void
-ifsbreakup(char *string, struct arglist *arglist)
-{
-	struct ifsregion *ifsp;
-	char *start;
-	char *p;
-	char *q;
-	const char *ifs;
-	const char *ifsspc;
-	int had_param_ch = 0;
-
-	start = string;
-
-	if (ifslastp == NULL) {
-		/* Return entire argument, IFS doesn't apply to any of it */
-		appendarglist(arglist, start);
-		return;
-	}
-
-	ifs = ifsset() ? ifsval() : " \t\n";
-
-	for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) {
-		p = string + ifsp->begoff;
-		while (p < string + ifsp->endoff) {
-			q = p;
-			if (*p == CTLESC)
-				p++;
-			if (ifsp->inquotes) {
-				/* Only NULs (should be from "$@") end args */
-				had_param_ch = 1;
-				if (*p != 0) {
-					p++;
-					continue;
-				}
-				ifsspc = NULL;
-			} else {
-				if (!strchr(ifs, *p)) {
-					had_param_ch = 1;
-					p++;
-					continue;
-				}
-				ifsspc = strchr(" \t\n", *p);
-
-				/* Ignore IFS whitespace at start */
-				if (q == start && ifsspc != NULL) {
-					p++;
-					start = p;
-					continue;
-				}
-				had_param_ch = 0;
-			}
-
-			/* Save this argument... */
-			*q = '\0';
-			appendarglist(arglist, start);
-			p++;
-
-			if (ifsspc != NULL) {
-				/* Ignore further trailing IFS whitespace */
-				for (; p < string + ifsp->endoff; p++) {
-					q = p;
-					if (*p == CTLESC)
-						p++;
-					if (strchr(ifs, *p) == NULL) {
-						p = q;
-						break;
-					}
-					if (strchr(" \t\n", *p) == NULL) {
-						p++;
-						break;
-					}
-				}
-			}
-			start = p;
-		}
-	}
-
-	/*
-	 * Save anything left as an argument.
-	 * Traditionally we have treated 'IFS=':'; set -- x$IFS' as
-	 * generating 2 arguments, the second of which is empty.
-	 * Some recent clarification of the Posix spec say that it
-	 * should only generate one....
-	 */
-	if (had_param_ch || *start != 0)
-		appendarglist(arglist, start);
-}
-
-
 static char expdir[PATH_MAX];
 #define expdir_end (expdir + sizeof(expdir))
 
 /*
  * Perform pathname generation and remove control characters.
- * At this point, the only control characters should be CTLESC and CTLQUOTEMARK.
+ * At this point, the only control characters should be CTLESC.
  * The results are stored in the list dstlist.
  */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list