Re: Debian Bug#429251: [PATCH] honor tab as IFS whitespace when splitting fields

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

Am Wednesday 10 June 2009 07:48:45 schrieben Sie:
> On Sat, May 30, 2009 at 10:33:00PM +0200, Stefan Potyra wrote:
> > Hi Herbert,
> >
> > thanks for your work wrt dash!
> >
> > forwarding the patch for debian bug 429251 to you, since I just found out
> > that I dropped the CC.
> >
> > Hope, that it's better this time.
>
> Thanks for the patch!
>
> Could you resend it and cc dash@xxxxxxxxxxxxxxx?
>

Of course, here you are.

Cheers,
     Stefan.
--- dash-0.5.5.1.orig/src/expand.c
+++ dash-0.5.5.1/src/expand.c
@@ -117,9 +117,9 @@
 STATIC size_t strtodest(const char *, const char *, int);
 STATIC void memtodest(const char *, size_t, const char *, int);
 STATIC ssize_t varvalue(char *, int, int);
-STATIC void recordregion(int, int, int);
-STATIC void removerecordregions(int); 
-STATIC void ifsbreakup(char *, struct arglist *);
+void recordregion(int, int, int);
+void removerecordregions(int); 
+void ifsbreakup(char *, struct arglist *);
 STATIC void ifsfree(void);
 STATIC void expandmeta(struct strlist *, int);
 #ifdef HAVE_GLOB
@@ -412,7 +412,7 @@
 }
 
 
-STATIC void 
+void 
 removerecordregions(int endoff)
 {
 	if (ifslastp == NULL)
@@ -999,7 +999,7 @@
  * string for IFS characters.
  */
 
-STATIC void
+void
 recordregion(int start, int end, int nulonly)
 {
 	struct ifsregion *ifsp;
@@ -1026,7 +1026,7 @@
  * strings to the argument list.  The regions of the string to be
  * searched for IFS characters have been stored by recordregion.
  */
-STATIC void
+void
 ifsbreakup(char *string, struct arglist *arglist)
 {
 	struct ifsregion *ifsp;
only in patch2:
unchanged:
--- dash-0.5.5.1.orig/src/miscbltin.c
+++ dash-0.5.5.1/src/miscbltin.c
@@ -55,18 +55,77 @@
 #include "miscbltin.h"
 #include "mystring.h"
 #include "main.h"
+#include "expand.h"
 
 #undef rflag
 
+/** handle one line of the read command.
+ *  more fields than variables -> remainder shall be part of last variable.
+ *  less fields than variables -> remaining variables unset.
+ *
+ *  @param line complete line of input
+ *  @param ap argument (variable) list
+ */
+static void
+readcmd_handle_line(char *line, char **ap)
+{
+	struct arglist arglist;
+	struct strlist *sl;
+	char *s, *backup;
+
+	/* ifsbreakup will fiddle stack region, need a copy */
+	s = savestr(line);
+	/* need yet another copy, so that delimiters aren't lost
+	 * in case there are more fields than variables */
+	backup = savestr(line);
+
+	arglist.lastp = &arglist.list;
+	recordregion(0, strlen(line), 0);
+	
+	ifsbreakup(s, &arglist);
+	*arglist.lastp = NULL;
+	removerecordregions(0);
+
+	for (sl = arglist.list; sl != NULL; sl = sl->next) {
+
+		/* remaining fields present, but no variables left. */
+		if ((*(ap + 1) == NULL) && (sl->next != NULL)) {
+			size_t offset;
+			const char *remainder;
+
+			/* FIXME little bit hacky, assuming that ifsbreakup 
+			 * will not modify the length of the string */
+			offset = sl->text - s;
+			remainder = backup + offset;
+			setvar(*ap, remainder, 0);
+
+			free(s);
+			free(backup);
+			return;
+		}
+		
+		/* set variable to field */
+		setvar(*ap, sl->text, 0);
+		ap++;
+	}
+
+	/* nullify remaining arguments */
+	for (; *ap != NULL; ap++) {
+		setvar(*ap, nullstr, 0);
+	}
+
+	free(s);
+	free(backup);
+}
 
 
 /*
  * The read builtin.  The -e option causes backslashes to escape the
- * following character.
+ * following character. The -p option followed by an argument prompts
+ * with the argument.
  *
  * This uses unbuffered input, which may be avoidable in some cases.
  */
-
 int
 readcmd(int argc, char **argv)
 {
@@ -75,14 +134,14 @@
 	char c;
 	int rflag;
 	char *prompt;
-	const char *ifs;
 	char *p;
-	int startword;
-	int status;
 	int i;
+	int res;
+	int status;
 
 	rflag = 0;
 	prompt = NULL;
+	status = 0;
 	while ((i = nextopt("p:r")) != '\0') {
 		if (i == 'p')
 			prompt = optionarg;
@@ -95,60 +154,53 @@
 		flushall();
 #endif
 	}
-	if (*(ap = argptr) == NULL)
+	if (*(ap = argptr) == NULL) {
 		sh_error("arg count");
-	if ((ifs = bltinlookup("IFS")) == NULL)
-		ifs = defifs;
-	status = 0;
-	startword = 1;
+	}
+
 	backslash = 0;
 	STARTSTACKSTR(p);
 	for (;;) {
-		if (read(0, &c, 1) != 1) {
+		/* read character by character until eol */
+		res = read(0, &c, 1);
+		if (res != 1) {
 			status = 1;
 			break;
 		}
-		if (c == '\0')
-			continue;
-		if (backslash) {
+
+		if (c == '\0') {
 			backslash = 0;
-			if (c != '\n')
-				goto put;
 			continue;
 		}
-		if (!rflag && c == '\\') {
-			backslash++;
-			continue;
-		}
-		if (c == '\n')
+	
+		/* eol reached, end loop */
+		if ((backslash == 0) && (c == '\n')) {
 			break;
-		if (startword && *ifs == ' ' && strchr(ifs, c)) {
+		}
+
+		/* preceeding backslash */
+		if (backslash != 0) {
+			backslash = 0;
+			if (c != '\n') {
+				STPUTC(c, p);
+			}
 			continue;
 		}
-		startword = 0;
-		if (ap[1] != NULL && strchr(ifs, c) != NULL) {
-			STACKSTRNUL(p);
-			setvar(*ap, stackblock(), 0);
-			ap++;
-			startword = 1;
-			STARTSTACKSTR(p);
-		} else {
-put:
-			STPUTC(c, p);
+
+		if ((! rflag) && (c == '\\')) {
+			backslash++;
+			continue;
 		}
+
+		backslash = 0;
+		STPUTC(c, p);
 	}
+
 	STACKSTRNUL(p);
-	/* Remove trailing blanks */
-	while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
-		*p = '\0';
-	setvar(*ap, stackblock(), 0);
-	while (*++ap != NULL)
-		setvar(*ap, nullstr, 0);
+	readcmd_handle_line(stackblock(), ap);
 	return status;
 }
 
-
-
 /*
  * umask builtin
  *

Attachment: signature.asc
Description: This is a digitally signed message part.


[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux