From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21986 invoked from network); 8 May 1998 06:54:06 -0000 Received: from math.gatech.edu (list@130.207.146.50) by ns1.primenet.com.au with SMTP; 8 May 1998 06:54:06 -0000 Received: (from list@localhost) by math.gatech.edu (8.8.5/8.8.5) id CAA11371; Fri, 8 May 1998 02:48:27 -0400 (EDT) Resent-Date: Fri, 8 May 1998 02:48:27 -0400 (EDT) From: Zoltan Hidvegi Message-Id: <199805080648.BAA03157@hzoli.home> Subject: PATCH: ksh $'...' syntax To: zsh-workers@math.gatech.edu (Zsh hacking and development) Date: Fri, 8 May 1998 01:48:43 -0500 (CDT) X-Mailer: ELM [version 2.4ME+ PL31 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Resent-Message-ID: <"GnRs73.0.Zn2.xggKr"@math> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/3952 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu This implements the $'...' quoting syntax from ksh93. Here is the ksh doc: A single quote cannot appear within the single quotes. A single quoted string preceded by an unquoted $ is processed as an ANSI-C string except that \0 within the string causes the remainder of the string to be ignored and \E is equivalent to the escape character (ascii 033). Zsh is a little bit different, it interprets the escapes the same way the print builtin does, and of course \0 within the string is allowed and does not cause the reminder ignored. This syntax is very useful to specify command line arguments with non-printable characters or newlines. Zoli *** Doc/Zsh/grammar.yo 1997/06/05 04:44:57 3.1.3.0 --- Doc/Zsh/grammar.yo 1997/06/06 06:13:24 3.1.3.1 *************** *** 305,312 **** A character may be var(quoted) (that is, made to stand for itself) by preceding it with a `tt(\)'. `tt(\)' followed by a newline is ignored. ! All characters enclosed between a pair of single quotes (tt('')) ! are quoted. A single quote cannot appear within single quotes. ! Inside double quotes (tt("")), parameter and command substitution ! occurs, and `tt(\)' quotes the characters `tt(\)', `tt(`)', `tt(")', and `tt($)'. --- 305,314 ---- A character may be var(quoted) (that is, made to stand for itself) by preceding it with a `tt(\)'. `tt(\)' followed by a newline is ignored. ! All characters enclosed between a pair of single quotes (tt('')) that ! is not preceeded by a `tt($)' are quoted. A single quote cannot appear ! within single quotes. A single quoted string preceded by an unquoted ! `tt($)' is processed the same way as the string arguments of the ! tt(print) builtin. Inside double quotes (tt("")), parameter and ! command substitution occurs, and `tt(\)' quotes the characters `tt(\)', `tt(`)', `tt(")', and `tt($)'. *** Src/lex.c 1997/06/05 04:44:57 3.1.3.0 --- Src/lex.c 1997/06/06 06:13:24 3.1.3.1 *************** gettokstr(int c, int sub) *** 936,948 **** if (lexstop) goto brk; break; ! case LX2_QUOTE: add(Snull); cmdpush(CS_QUOTE); for (;;) { STOPHIST while ((c = hgetc()) != '\'' && !lexstop) { ! if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') { if (bptr[-1] == '\\') bptr--, len--; else --- 936,955 ---- if (lexstop) goto brk; break; ! case LX2_QUOTE: { ! int strquote = (len && bptr[-1] == String); ! add(Snull); cmdpush(CS_QUOTE); for (;;) { STOPHIST while ((c = hgetc()) != '\'' && !lexstop) { ! if (strquote && c == '\\') { ! add(c); ! c = hgetc(); ! if (lexstop) ! break; ! } else if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') { if (bptr[-1] == '\\') bptr--, len--; else *************** gettokstr(int c, int sub) *** 967,972 **** --- 974,980 ---- lexstop = 0; c = Snull; break; + } case LX2_DQUOTE: add(Dnull); cmdpush(CS_DQUOTE); *************** skipcomm(void) *** 1347,1359 **** add(c); c = hgetc(); break; ! case '\'': add(c); STOPHIST ! while ((c = hgetc()) != '\'' && !lexstop) add(c); ALLOWHIST break; case '\"': add(c); while ((c = hgetc()) != '\"' && !lexstop) --- 1355,1374 ---- add(c); c = hgetc(); break; ! case '\'': { ! int strquote = bptr[-1] == '$'; add(c); STOPHIST ! while ((c = hgetc()) != '\'' && !lexstop) { ! if (c == '\\' && strquote) { ! add(c); ! c = hgetc(); ! } add(c); + } ALLOWHIST break; + } case '\"': add(c); while ((c = hgetc()) != '\"' && !lexstop) *** Src/subst.c 1997/06/05 04:44:57 3.1.3.0 --- Src/subst.c 1997/06/06 06:13:24 3.1.3.1 *************** stringsubst(LinkList list, LinkNode node *** 114,119 **** --- 114,122 ---- str = arithsubst(str + 2, &str3, str2); setdata(node, (void *) str3); continue; + } else if (str[1] == Snull) { + str = getkeystring(str, NULL, 4, NULL); + continue; } else { node = paramsubst(list, node, &str, qt, ssub); if (errflag || !node) *** Src/utils.c 1997/06/05 04:44:57 3.1.3.0 --- Src/utils.c 1997/06/06 06:13:24 3.1.3.1 *************** dquotedzputs(char const *s, FILE *stream *** 3142,3153 **** char * getkeystring(char *s, int *len, int fromwhere, int *misc) { ! char *buf = halloc(strlen(s) + 1); ! char *t = buf, *u = NULL; char svchar = '\0'; int meta = 0, control = 0; ! for (; *s; s++) { if (*s == '\\' && s[1]) { switch (*++s) { case 'a': --- 3142,3159 ---- char * getkeystring(char *s, int *len, int fromwhere, int *misc) { ! char *buf; ! char *t, *u = NULL; char svchar = '\0'; int meta = 0, control = 0; ! if (fromwhere != 4) ! buf = halloc(strlen(s) + 1); ! else { ! buf = s; ! s += 2; ! } ! for (t = buf; *s; s++) { if (*s == '\\' && s[1]) { switch (*++s) { case 'a': *************** getkeystring(char *s, int *len, int from *** 3235,3240 **** --- 3241,3249 ---- } break; } + } else if (fromwhere == 4 && *s == Snull) { + for (u = t; (*u++ = *s++);); + return t + 1; } else if (*s == '^' && fromwhere == 2) { control = 1; continue; *************** getkeystring(char *s, int *len, int from *** 3257,3263 **** --- 3266,3278 ---- t[-1] |= 0x80; meta = 0; } + if (fromwhere == 4 && imeta(t[-1])) { + *t = t[-1] ^ 32; + t[-1] = Meta; + t++; + } } + DPUTS(fromwhere == 4, "BUG: unterminated $' substitution"); *t = '\0'; *len = t - buf; return buf;