Advertisement
Guest User

Untitled

a guest
Mar 29th, 2017
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 3.39 KB | None | 0 0
  1. diff --git a/options/m_property.c b/options/m_property.c
  2. index 9dad34f..c7c92b2 100644
  3. --- a/options/m_property.c
  4. +++ b/options/m_property.c
  5. @@ -255,6 +255,21 @@ static int expand_property(const struct m_property *prop_list, char **ret,
  6.      return skip;
  7.  }
  8.  
  9. +// This is not really a functional/generic macro but rather a sequence which
  10. +// can only execute inside m_properties_expand_string. The arguments are there
  11. +// only to make its usage semantic clearer.
  12. +// Effectively it's: ret = ret[0 .. from] + expand( ret[from .. ret_len] )
  13. +// while keeping ret_len up to date, and managing memory transparently.
  14. +#define EXPAND_INPLACE(ret, from, ret_len) do {                           \
  15. +    MP_TARRAY_APPEND(NULL, ret, ret_len, '\0');                           \
  16. +    char *out0 = m_properties_expand_string(prop_list, ret + from, ctx);  \
  17. +    int out_len = strlen(out0);                                           \
  18. +    ret = talloc_realloc(NULL, ret, char, from + out_len);                \
  19. +    memcpy(ret + from, out0, out_len);                                    \
  20. +    ret_len = from + out_len;                                             \
  21. +    talloc_free(out0);                                                    \
  22. +} while (0)
  23. +
  24.  char *m_properties_expand_string(const struct m_property *prop_list,
  25.                                   const char *str0, void *ctx)
  26.  {
  27. @@ -264,15 +279,34 @@ char *m_properties_expand_string(const struct m_property *prop_list,
  28.      int level = 0, skip_level = 0;
  29.      bstr str = bstr0(str0);
  30.  
  31. +    // Stack where at index i we store -1 if level i+1 doesn't need re-expand
  32. +    // once it's done, or the output position from which we should re-expand.
  33. +    // E.g. for the string "${X}${+Y:abc${Z}}", the array will be [-1] while
  34. +    // expanding X, [N] while expanding Y, and [N, -1] while (if) expanding Z,
  35. +    // where N is the output size after expanding ${X}.
  36. +    int *reexpand_stack = NULL;
  37. +    int reexpand_len = 0;  // identical to level, kept separate for readability.
  38. +
  39.      while (str.len) {
  40.          if (level > 0 && bstr_eatstart0(&str, "}")) {
  41.              if (skip && level <= skip_level)
  42.                  skip = false;
  43.              level--;
  44. +
  45. +            int from = reexpand_stack[level];  // pop
  46. +            MP_TARRAY_REMOVE_AT(reexpand_stack, reexpand_len, level);
  47. +            if (from >= 0)  // re-expand the level's output
  48. +                EXPAND_INPLACE(ret, from, ret_len);
  49.          } else if (bstr_startswith0(str, "${") && bstr_find0(str, "}") >= 0) {
  50.              str = bstr_cut(str, 2);
  51.              level++;
  52.  
  53. +            // "${+" means we need to re-expand the output of the entire section.
  54. +            // If we see '+', store the current ret_len as the starting point
  55. +            // for re-expand which we'll use once we're done with this level.
  56. +            int from = bstr_eatstart0(&str, "+") ? ret_len : -1;
  57. +            MP_TARRAY_APPEND(NULL, reexpand_stack, reexpand_len, from); // push
  58. +
  59.              // Assume ":" and "}" can't be part of the property name
  60.              // => if ":" comes before "}", it must be for the fallback
  61.              int term_pos = bstrcspn(str, ":}");
  62. @@ -308,6 +342,8 @@ char *m_properties_expand_string(const struct m_property *prop_list,
  63.      }
  64.  
  65.      MP_TARRAY_APPEND(NULL, ret, ret_len, '\0');
  66. +    if (reexpand_stack)
  67. +        talloc_free(reexpand_stack);
  68.      return ret;
  69.  }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement