📄 braces.c
字号:
t = (char *)xmalloc (2); t[0] = n; t[1] = '\0'; result[i++] = t; } n += incr; if ((incr < 0 && n < end) || (incr > 0 && n > end)) break; } while (1); result[i] = (char *)0; return (result);}static char **expand_seqterm (text, tlen) char *text; size_t tlen;{ char *t, *lhs, *rhs; int i, lhs_t, rhs_t, incr, lhs_l, rhs_l, width; intmax_t lhs_v, rhs_v; intmax_t tl, tr; char **result, *ep, *oep; t = strstr (text, BRACE_SEQ_SPECIFIER); if (t == 0) return ((char **)NULL); lhs_l = t - text; /* index of start of BRACE_SEQ_SPECIFIER */ lhs = substring (text, 0, lhs_l); rhs = substring (text, lhs_l + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen); if (lhs[0] == 0 || rhs[0] == 0) { free (lhs); free (rhs); return ((char **)NULL); } /* Now figure out whether LHS and RHS are integers or letters. Both sides have to match. */ lhs_t = (legal_number (lhs, &tl)) ? ST_INT : ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD); /* Decide on rhs and whether or not it looks like the user specified an increment */ ep = 0; if (ISDIGIT (rhs[0]) || ((rhs[0] == '+' || rhs[0] == '-') && ISDIGIT (rhs[1]))) { rhs_t = ST_INT; tr = strtoimax (rhs, &ep, 10); if (ep && *ep != 0 && *ep != '.') rhs_t = ST_BAD; /* invalid */ } else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.')) { rhs_t = ST_CHAR; ep = rhs + 1; } else { rhs_t = ST_BAD; ep = 0; } incr = 1; if (rhs_t != ST_BAD) { oep = ep; if (ep && *ep == '.' && ep[1] == '.' && ep[2]) incr = strtoimax (ep + 2, &ep, 10); if (*ep != 0) rhs_t = ST_BAD; /* invalid incr */ tlen -= ep - oep; } if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD) { free (lhs); free (rhs); return ((char **)NULL); } /* OK, we have something. It's either a sequence of integers, ascending or descending, or a sequence or letters, ditto. Generate the sequence, put it into a string vector, and return it. */ if (lhs_t == ST_CHAR) { lhs_v = (unsigned char)lhs[0]; rhs_v = (unsigned char)rhs[0]; width = 1; } else { lhs_v = tl; /* integer truncation */ rhs_v = tr; /* Decide whether or not the terms need zero-padding */ rhs_l = tlen - lhs_l - sizeof (BRACE_SEQ_SPECIFIER) + 1; width = 0; if (lhs_l > 1 && lhs[0] == '0') width = lhs_l, lhs_t = ST_ZINT; if (lhs_l > 2 && lhs[0] == '-' && lhs[1] == '0') width = lhs_l, lhs_t = ST_ZINT; if (rhs_l > 1 && rhs[0] == '0' && width < rhs_l) width = rhs_l, lhs_t = ST_ZINT; if (rhs_l > 2 && rhs[0] == '-' && rhs[1] == '0' && width < rhs_l) width = rhs_l, lhs_t = ST_ZINT; if (width < lhs_l && lhs_t == ST_ZINT) width = lhs_l; if (width < rhs_l && lhs_t == ST_ZINT) width = rhs_l; } result = mkseq (lhs_v, rhs_v, incr, lhs_t, width); free (lhs); free (rhs); return (result);}/* Start at INDEX, and skip characters in TEXT. Set INDEX to the index of the character matching SATISFY. This understands about quoting. Return the character that caused us to stop searching; this is either the same as SATISFY, or 0. *//* If SATISFY is `}', we are looking for a brace expression, so we should enforce the rules that govern valid brace expansions: 1) to count as an arg separator, a comma or `..' has to be outside an inner set of braces. */static intbrace_gobbler (text, tlen, indx, satisfy) char *text; size_t tlen; int *indx; int satisfy;{ register int i, c, quoted, level, commas, pass_next;#if defined (SHELL) int si; char *t;#endif DECLARE_MBSTATE; level = quoted = pass_next = 0;#if defined (CSH_BRACE_COMPAT) commas = 1;#else commas = (satisfy == '}') ? 0 : 1;#endif i = *indx; while (c = text[i]) { if (pass_next) { pass_next = 0; ADVANCE_CHAR (text, tlen, i); continue; } /* A backslash escapes the next character. This allows backslash to escape the quote character in a double-quoted string. */ if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`')) { pass_next = 1; i++; continue; }#if defined (SHELL) /* If compiling for the shell, treat ${...} like \{...} */ if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */ { pass_next = 1; i++; if (quoted == 0) level++; continue; }#endif if (quoted) { if (c == quoted) quoted = 0; ADVANCE_CHAR (text, tlen, i); continue; } if (c == '"' || c == '\'' || c == '`') { quoted = c; i++; continue; }#if defined (SHELL) /* Pass new-style command and process substitutions through unchanged. */ if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */ { si = i + 2; t = extract_command_subst (text, &si, 0); i = si; free (t); i++; continue; }#endif if (c == satisfy && level == 0 && quoted == 0 && commas > 0) { /* We ignore an open brace surrounded by whitespace, and also an open brace followed immediately by a close brace preceded by whitespace. */ if (c == '{' && ((!i || brace_whitespace (text[i - 1])) && (brace_whitespace (text[i + 1]) || text[i + 1] == '}'))) { i++; continue; } break; } if (c == '{') level++; else if (c == '}' && level) level--;#if !defined (CSH_BRACE_COMPAT) else if (satisfy == '}' && c == brace_arg_separator && level == 0) commas++; else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) && text[i+2] != satisfy && level == 0) commas++;#endif ADVANCE_CHAR (text, tlen, i); } *indx = i; return (c);}/* Return a new array of strings which is the result of appending each string in ARR2 to each string in ARR1. The resultant array is len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents) are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2 is returned. */static char **array_concat (arr1, arr2) char **arr1, **arr2;{ register int i, j, len, len1, len2; register char **result; if (arr1 == 0) return (strvec_copy (arr2)); if (arr2 == 0) return (strvec_copy (arr1)); len1 = strvec_len (arr1); len2 = strvec_len (arr2); result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *)); len = 0; for (i = 0; i < len1; i++) { int strlen_1 = strlen (arr1[i]); for (j = 0; j < len2; j++) { result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j])); strcpy (result[len], arr1[i]); strcpy (result[len] + strlen_1, arr2[j]); len++; } free (arr1[i]); } free (arr1); result[len] = (char *)NULL; return (result);}#if defined (TEST)#include <stdio.h>fatal_error (format, arg1, arg2) char *format, *arg1, *arg2;{ report_error (format, arg1, arg2); exit (1);}report_error (format, arg1, arg2) char *format, *arg1, *arg2;{ fprintf (stderr, format, arg1, arg2); fprintf (stderr, "\n");}main (){ char example[256]; for (;;) { char **result; int i; fprintf (stderr, "brace_expand> "); if ((!fgets (example, 256, stdin)) || (strncmp (example, "quit", 4) == 0)) break; if (strlen (example)) example[strlen (example) - 1] = '\0'; result = brace_expand (example); for (i = 0; result[i]; i++) printf ("%s\n", result[i]); free_array (result); }}/* * Local variables: * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o" * end: */#endif /* TEST */#endif /* BRACE_EXPANSION */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -