📄 subst.c
字号:
dolbrace_state = DOLBRACE_QUOTE; else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1) dolbrace_state = DOLBRACE_QUOTE; else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1) dolbrace_state = DOLBRACE_QUOTE; else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1) dolbrace_state = DOLBRACE_QUOTE; else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1) dolbrace_state = DOLBRACE_QUOTE; else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0) dolbrace_state = DOLBRACE_OP; else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0) dolbrace_state = DOLBRACE_WORD; } if (c == 0 && nesting_level) { if (no_longjmp_on_fatal_error == 0) { /* { */ report_error (_("bad substitution: no closing `%s' in %s"), "}", string); last_command_exit_value = EXECUTION_FAILURE; exp_jump_to_top_level (DISCARD); } else { *sindex = i; return ((char *)NULL); } } result = (flags & SX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i); *sindex = i; return (result);}/* Remove backslashes which are quoting backquotes from STRING. Modifies STRING, and returns a pointer to it. */char *de_backslash (string) char *string;{ register size_t slen; register int i, j, prev_i; DECLARE_MBSTATE; slen = strlen (string); i = j = 0; /* Loop copying string[i] to string[j], i >= j. */ while (i < slen) { if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' || string[i + 1] == '$')) i++; prev_i = i; ADVANCE_CHAR (string, slen, i); if (j < prev_i) do string[j++] = string[prev_i++]; while (prev_i < i); else j = i; } string[j] = '\0'; return (string);}#if 0/*UNUSED*//* Replace instances of \! in a string with !. */voidunquote_bang (string) char *string;{ register int i, j; register char *temp; temp = (char *)xmalloc (1 + strlen (string)); for (i = 0, j = 0; (temp[j] = string[i]); i++, j++) { if (string[i] == '\\' && string[i + 1] == '!') { temp[j] = '!'; i++; } } strcpy (string, temp); free (temp);}#endif#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)/* This function assumes s[i] == open; returns with s[ret] == close; used to parse array subscripts. FLAGS & 1 means to not attempt to skip over matched pairs of quotes or backquotes, or skip word expansions; it is intended to be used after expansion has been performed and during final assignment parsing (see arrayfunc.c:assign_compound_array_list()). */static intskip_matched_pair (string, start, open, close, flags) const char *string; int start, open, close, flags;{ int i, pass_next, backq, si, c, count; size_t slen; char *temp, *ss; DECLARE_MBSTATE; slen = strlen (string + start) + start; no_longjmp_on_fatal_error = 1; i = start + 1; /* skip over leading bracket */ count = 1; pass_next = backq = 0; ss = (char *)string; while (c = string[i]) { if (pass_next) { pass_next = 0; if (c == 0) CQ_RETURN(i); ADVANCE_CHAR (string, slen, i); continue; } else if (c == '\\') { pass_next = 1; i++; continue; } else if (backq) { if (c == '`') backq = 0; ADVANCE_CHAR (string, slen, i); continue; } else if ((flags & 1) == 0 && c == '`') { backq = 1; i++; continue; } else if ((flags & 1) == 0 && c == open) { count++; i++; continue; } else if (c == close) { count--; if (count == 0) break; i++; continue; } else if ((flags & 1) == 0 && (c == '\'' || c == '"')) { i = (c == '\'') ? skip_single_quoted (ss, slen, ++i) : skip_double_quoted (ss, slen, ++i); /* no increment, the skip functions increment past the closing quote. */ } else if ((flags&1) == 0 && c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE)) { si = i + 2; if (string[si] == '\0') CQ_RETURN(si); if (string[i+1] == LPAREN) temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ else temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC); i = si; if (string[i] == '\0') /* don't increment i past EOS in loop */ break; i++; continue; } else ADVANCE_CHAR (string, slen, i); } CQ_RETURN(i);}#if defined (ARRAY_VARS)intskipsubscript (string, start, flags) const char *string; int start, flags;{ return (skip_matched_pair (string, start, '[', ']', flags));}#endif/* Skip characters in STRING until we find a character in DELIMS, and return the index of that character. START is the index into string at which we begin. This is similar in spirit to strpbrk, but it returns an index into STRING and takes a starting index. This little piece of code knows quite a lot of shell syntax. It's very similar to skip_double_quoted and other functions of that ilk. */intskip_to_delim (string, start, delims, flags) char *string; int start; char *delims; int flags;{ int i, pass_next, backq, si, c, invert, skipquote, skipcmd; size_t slen; char *temp, open[3]; DECLARE_MBSTATE; slen = strlen (string + start) + start; if (flags & SD_NOJMP) no_longjmp_on_fatal_error = 1; invert = (flags & SD_INVERT); skipcmd = (flags & SD_NOSKIPCMD) == 0; i = start; pass_next = backq = 0; while (c = string[i]) { /* If this is non-zero, we should not let quote characters be delimiters and the current character is a single or double quote. We should not test whether or not it's a delimiter until after we skip single- or double-quoted strings. */ skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"')); if (pass_next) { pass_next = 0; if (c == 0) CQ_RETURN(i); ADVANCE_CHAR (string, slen, i); continue; } else if (c == '\\') { pass_next = 1; i++; continue; } else if (backq) { if (c == '`') backq = 0; ADVANCE_CHAR (string, slen, i); continue; } else if (c == '`') { backq = 1; i++; continue; } else if (skipquote == 0 && invert == 0 && member (c, delims)) break; else if (c == '\'' || c == '"') { i = (c == '\'') ? skip_single_quoted (string, slen, ++i) : skip_double_quoted (string, slen, ++i); /* no increment, the skip functions increment past the closing quote. */ } else if (c == '$' && ((skipcmd && string[i+1] == LPAREN) || string[i+1] == LBRACE)) { si = i + 2; if (string[si] == '\0') CQ_RETURN(si); if (string[i+1] == LPAREN) temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */ else temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC); i = si; if (string[i] == '\0') /* don't increment i past EOS in loop */ break; i++; continue; }#if defined (PROCESS_SUBSTITUTION) else if (skipcmd && (c == '<' || c == '>') && string[i+1] == LPAREN) { si = i + 2; if (string[si] == '\0') CQ_RETURN(si); temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si); i = si; if (string[i] == '\0') break; i++; continue; }#endif /* PROCESS_SUBSTITUTION */#if defined (EXTENDED_GLOB) else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@")) { si = i + 2; if (string[si] == '\0') CQ_RETURN(si); open[0] = c; open[1] = LPAREN; open[2] = '\0'; temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */ i = si; if (string[i] == '\0') /* don't increment i past EOS in loop */ break; i++; continue; }#endif else if ((skipquote || invert) && (member (c, delims) == 0)) break; else ADVANCE_CHAR (string, slen, i); } CQ_RETURN(i);}#if defined (READLINE)/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is an unclosed quoted string), or if the character at EINDEX is quoted by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various single and double-quoted string parsing functions should not return an error if there are unclosed quotes or braces. The characters that this recognizes need to be the same as the contents of rl_completer_quote_characters. */intchar_is_quoted (string, eindex) char *string; int eindex;{ int i, pass_next, c; size_t slen; DECLARE_MBSTATE; slen = strlen (string); no_longjmp_on_fatal_error = 1; i = pass_next = 0; while (i <= eindex) { c = string[i]; if (pass_next) { pass_next = 0; if (i >= eindex) /* XXX was if (i >= eindex - 1) */ CQ_RETURN(1); ADVANCE_CHAR (string, slen, i); continue; } else if (c == '\\') { pass_next = 1; i++; continue; } else if (c == '\'' || c == '"') { i = (c == '\'') ? skip_single_quoted (string, slen, ++i) : skip_double_quoted (string, slen, ++i); if (i > eindex) CQ_RETURN(1); /* no increment, the skip_xxx functions go one past end */ } else ADVANCE_CHAR (string, slen, i); } CQ_RETURN(0);}intunclosed_pair (string, eindex, openstr) char *string; int eindex; char *openstr;{ int i, pass_next, openc, olen; size_t slen; DECLARE_MBSTATE; slen = strlen (string); olen = strlen (openstr); i = pass_next = openc = 0; while (i <= eindex) { if (pass_next) { pass_next = 0; if (i >= eindex) /* XXX was if (i >= eindex - 1) */ return 0; ADVANCE_CHAR (string, slen, i); continue; } else if (string[i] == '\\') { pass_next = 1; i++; continue; } else if (STREQN (string + i, openstr, olen)) { openc = 1 - openc; i += olen; } else if (string[i] == '\'' || string[i] == '"') { i = (string[i] == '\'') ? skip_single_quoted (string, slen, i) : skip_double_quoted (string, slen, i); if (i > eindex) return 0; } else ADVANCE_CHAR (string, slen, i); } return (openc);}/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the individual words. If DELIMS is NULL, the current value of $IFS is used to split the string, and the function follows the shell field splitting rules. SENTINEL is an index to look for. NWP, if non-NULL, gets the number of words in the returned list. CWP, if non-NULL, gets the index of the word containing SENTINEL. Non-whitespace chars in DELIMS delimit separate fields. */WORD_LIST *split_at_delims (string, slen, delims, sentinel, flags, nwp, cwp) char *string; int slen; char *delims; int sentinel, flags; int *nwp, *cwp;{ int ts, te, i, nw, cw, ifs_split, dflags; char *token, *d, *d2; WORD_LIST *ret, *tl; if (string == 0 || *string == '\0') { if (nwp) *nwp = 0; if (cwp) *cwp = 0; return ((WORD_LIST *)NULL); } d = (delims == 0) ? ifs_value : delims; ifs_split = delims == 0; /* Make d2 the non-whitespace characters in delims */ d2 = 0; if (delims) { size_t slength;#if defined (HANDLE_MULTIBYTE) size_t mblength = 1;#endif DECLARE_MBSTATE; slength = strlen (delims); d2 = (char *)xmalloc (slength + 1); i = ts = 0; while (delims[i]) {#if defined (HANDLE_MULTIBYTE) mbstate_t state_bak; state_bak = state; mblength = MBRLEN (delims + i, slength, &state); if (MB_INVALIDCH (mblength)) state = state_bak; else if (mblength > 1) { memcpy (d2 + ts, delims + i, mblength); ts += mblength; i += mblength; slength -= mblength; continue; }#endif if (whitespace (delims[i]) == 0) d2[ts++] = delims[i]; i++; slength--; } d2[ts] = '\0'; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -