📄 subst.c
字号:
#ifdef INCLUDE_UNUSED/* Return the length of S, skipping over quoted characters */static intquoted_strlen (s) char *s;{ register char *p; int i; i = 0; for (p = s; *p; p++) { if (*p == CTLESC) { p++; if (*p == 0) return (i + 1); } i++; } return i;}#endif/* Find the first occurrence of character C in string S, obeying shell quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters escaped with CTLESC are skipped. */static char *quoted_strchr (s, c, flags) char *s; int c, flags;{ register char *p; for (p = s; *p; p++) { if (((flags & ST_BACKSL) && *p == '\\') || ((flags & ST_CTLESC) && *p == CTLESC)) { p++; if (*p == '\0') return ((char *)NULL); continue; } else if (*p == c) return p; } return ((char *)NULL);}/* Return 1 if CHARACTER appears in an unquoted portion of STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */static intunquoted_member (character, string) int character; char *string;{ size_t slen; int sindex, c; DECLARE_MBSTATE; slen = strlen (string); sindex = 0; while (c = string[sindex]) { if (c == character) return (1); switch (c) { default: ADVANCE_CHAR (string, slen, sindex); break; case '\\': sindex++; if (string[sindex]) ADVANCE_CHAR (string, slen, sindex); break; case '\'': sindex = skip_single_quoted (string, slen, ++sindex); break; case '"': sindex = skip_double_quoted (string, slen, ++sindex); break; } } return (0);}/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */static intunquoted_substring (substr, string) char *substr, *string;{ size_t slen; int sindex, c, sublen; DECLARE_MBSTATE; if (substr == 0 || *substr == '\0') return (0); slen = strlen (string); sublen = strlen (substr); for (sindex = 0; c = string[sindex]; ) { if (STREQN (string + sindex, substr, sublen)) return (1); switch (c) { case '\\': sindex++; if (string[sindex]) ADVANCE_CHAR (string, slen, sindex); break; case '\'': sindex = skip_single_quoted (string, slen, ++sindex); break; case '"': sindex = skip_double_quoted (string, slen, ++sindex); break; default: ADVANCE_CHAR (string, slen, sindex); break; } } return (0);}/* Most of the substitutions must be done in parallel. In order to avoid using tons of unclear goto's, I have some functions for manipulating malloc'ed strings. They all take INDX, a pointer to an integer which is the offset into the string where manipulation is taking place. They also take SIZE, a pointer to an integer which is the current length of the character array for this string. *//* Append SOURCE to TARGET at INDEX. SIZE is the current amount of space allocated to TARGET. SOURCE can be NULL, in which case nothing happens. Gets rid of SOURCE by freeing it. Returns TARGET in case the location has changed. */INLINE char *sub_append_string (source, target, indx, size) char *source, *target; int *indx, *size;{ if (source) { int srclen, n; srclen = STRLEN (source); if (srclen >= (int)(*size - *indx)) { n = srclen + *indx; n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE); target = (char *)xrealloc (target, (*size = n)); } FASTCOPY (source, target + *indx, srclen); *indx += srclen; target[*indx] = '\0'; free (source); } return (target);}#if 0/* UNUSED *//* Append the textual representation of NUMBER to TARGET. INDX and SIZE are as in SUB_APPEND_STRING. */char *sub_append_number (number, target, indx, size) intmax_t number; int *indx, *size; char *target;{ char *temp; temp = itos (number); return (sub_append_string (temp, target, indx, size));}#endif/* Extract a substring from STRING, starting at SINDEX and ending with one of the characters in CHARLIST. Don't make the ending character part of the string. Leave SINDEX pointing at the ending character. Understand about backslashes in the string. If (flags & SX_VARNAME) is non-zero, and array variables have been compiled into the shell, everything between a `[' and a corresponding `]' is skipped over. If (flags & SX_NOALLOC) is non-zero, don't return the substring, just update SINDEX. If (flags & SX_REQMATCH) is non-zero, the string must contain a closing character from CHARLIST. */static char *string_extract (string, sindex, charlist, flags) char *string; int *sindex; char *charlist; int flags;{ register int c, i; int found; size_t slen; char *temp; DECLARE_MBSTATE; slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0; i = *sindex; found = 0; while (c = string[i]) { if (c == '\\') { if (string[i + 1]) i++; else break; }#if defined (ARRAY_VARS) else if ((flags & SX_VARNAME) && c == '[') { int ni; /* If this is an array subscript, skip over it and continue. */ ni = skipsubscript (string, i, 0); if (string[ni] == ']') i = ni; }#endif else if (MEMBER (c, charlist)) { found = 1; break; } ADVANCE_CHAR (string, slen, i); } /* If we had to have a matching delimiter and didn't find one, return an error and let the caller deal with it. */ if ((flags & SX_REQMATCH) && found == 0) { *sindex = i; return (&extract_string_error); } temp = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); *sindex = i; return (temp);}/* Extract the contents of STRING as if it is enclosed in double quotes. SINDEX, when passed in, is the offset of the character immediately following the opening double quote; on exit, SINDEX is left pointing after the closing double quote. If STRIPDQ is non-zero, unquoted double quotes are stripped and the string is terminated by a null byte. Backslashes between the embedded double quotes are processed. If STRIPDQ is zero, an unquoted `"' terminates the string. */static char *string_extract_double_quoted (string, sindex, stripdq) char *string; int *sindex, stripdq;{ size_t slen; char *send; int j, i, t; unsigned char c; char *temp, *ret; /* The new string we return. */ int pass_next, backquote, si; /* State variables for the machine. */ int dquote; DECLARE_MBSTATE; slen = strlen (string + *sindex) + *sindex; send = string + slen; pass_next = backquote = dquote = 0; temp = (char *)xmalloc (1 + slen - *sindex); j = 0; i = *sindex; while (c = string[i]) { /* Process a character that was quoted by a backslash. */ if (pass_next) { /* XXX - take another look at this in light of Interp 221 */ /* Posix.2 sez: ``The backslash shall retain its special meaning as an escape character only when followed by one of the characters: $ ` " \ <newline>''. If STRIPDQ is zero, we handle the double quotes here and let expand_word_internal handle the rest. If STRIPDQ is non-zero, we have already been through one round of backslash stripping, and want to strip these backslashes only if DQUOTE is non-zero, indicating that we are inside an embedded double-quoted string. */ /* If we are in an embedded quoted string, then don't strip backslashes before characters for which the backslash retains its special meaning, but remove backslashes in front of other characters. If we are not in an embedded quoted string, don't strip backslashes at all. This mess is necessary because the string was already surrounded by double quotes (and sh has some really weird quoting rules). The returned string will be run through expansion as if it were double-quoted. */ if ((stripdq == 0 && c != '"') || (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0))) temp[j++] = '\\'; pass_next = 0;add_one_character: COPY_CHAR_I (temp, j, string, send, i); continue; } /* A backslash protects the next character. The code just above handles preserving the backslash in front of any character but a double quote. */ if (c == '\\') { pass_next++; i++; continue; } /* Inside backquotes, ``the portion of the quoted string from the initial backquote and the characters up to the next backquote that is not preceded by a backslash, having escape characters removed, defines that command''. */ if (backquote) { if (c == '`') backquote = 0; temp[j++] = c; i++; continue; } if (c == '`') { temp[j++] = c; backquote++; i++; continue; } /* Pass everything between `$(' and the matching `)' or a quoted ${ ... } pair through according to the Posix.2 specification. */ if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) { int free_ret = 1; si = i + 2; if (string[i + 1] == LPAREN) ret = extract_command_subst (string, &si, 0); else ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0); temp[j++] = '$'; temp[j++] = string[i + 1]; /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error is set. */ if (ret == 0 && no_longjmp_on_fatal_error) { free_ret = 0; ret = string + i + 2; } for (t = 0; ret[t]; t++, j++) temp[j] = ret[t]; temp[j] = string[si]; if (string[si]) { j++; i = si + 1; } else i = si; if (free_ret) free (ret); continue; } /* Add any character but a double quote to the quoted string we're accumulating. */ if (c != '"') goto add_one_character; /* c == '"' */ if (stripdq) { dquote ^= 1; i++; continue; } break; } temp[j] = '\0'; /* Point to after the closing quote. */ if (c) i++; *sindex = i; return (temp);}/* This should really be another option to string_extract_double_quoted. */static intskip_double_quoted (string, slen, sind) char *string; size_t slen; int sind;{ int c, i; char *ret; int pass_next, backquote, si; DECLARE_MBSTATE; pass_next = backquote = 0; i = sind; while (c = string[i]) { if (pass_next) { pass_next = 0; ADVANCE_CHAR (string, slen, i); continue; } else if (c == '\\') { pass_next++; i++; continue; } else if (backquote) { if (c == '`') backquote = 0; ADVANCE_CHAR (string, slen, i); continue; } else if (c == '`') { backquote++; i++; continue; } else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE))) { si = i + 2; if (string[i + 1] == LPAREN) ret = extract_command_subst (string, &si, SX_NOALLOC); else ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_NOALLOC); i = si + 1; continue; } else if (c != '"') { ADVANCE_CHAR (string, slen, i); continue; } else break; } if (c) i++; return (i);}/* Extract the contents of STRING as if it is enclosed in single quotes. SINDEX, when passed in, is the offset of the character immediately following the opening single quote; on exit, SINDEX is left pointing after the closing single quote. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -