| 17 | /* mac_parse - split string into literal text and macro references */ |
| 18 | |
| 19 | int mac_parse(const char *value, MAC_PARSE_FN action, void *context) |
| 20 | { |
| 21 | const char *myname = "mac_parse"; |
| 22 | ACL_VSTRING *buf = acl_vstring_alloc(1); /* result buffer */ |
| 23 | const char *vp; /* value pointer */ |
| 24 | const char *pp; /* open_paren pointer */ |
| 25 | const char *ep; /* string end pointer */ |
| 26 | static char open_paren[] = "({"; |
| 27 | static char close_paren[] = ")}"; |
| 28 | int level; |
| 29 | int status = 0; |
| 30 | |
| 31 | #define SKIP(start, var, cond) \ |
| 32 | for (var = start; *var && (cond); var++); |
| 33 | |
| 34 | acl_debug(DEBUG_MAC, 2) ("%s: %s", myname, value); |
| 35 | |
| 36 | for (vp = value; *vp;) { |
| 37 | if (*vp != '$') { /* ordinary character */ |
| 38 | ACL_VSTRING_ADDCH(buf, *vp); |
| 39 | vp += 1; |
| 40 | } else if (vp[1] == '$') { /* $$ becomes $ */ |
| 41 | ACL_VSTRING_ADDCH(buf, *vp); |
| 42 | vp += 2; |
| 43 | } else { /* found bare $ */ |
| 44 | if (ACL_VSTRING_LEN(buf) > 0) |
| 45 | MAC_PARSE_ACTION(status, MAC_PARSE_LITERAL, buf, context); |
| 46 | vp += 1; |
| 47 | pp = open_paren; |
| 48 | if (*vp == *pp || *vp == *++pp) { /* ${x} or $(x) */ |
| 49 | level = 1; |
| 50 | vp += 1; |
| 51 | for (ep = vp; level > 0; ep++) { |
| 52 | if (*ep == 0) { |
| 53 | acl_msg_warn("truncated macro reference: \"%s\"", value); |
| 54 | status |= MAC_PARSE_ERROR; |
| 55 | break; |
| 56 | } |
| 57 | if (*ep == *pp) |
| 58 | level++; |
| 59 | if (*ep == close_paren[pp - open_paren]) |
| 60 | level--; |
| 61 | } |
| 62 | if (status & MAC_PARSE_ERROR) |
| 63 | break; |
| 64 | acl_vstring_strncat(buf, vp, level > 0 ? ep - vp : ep - vp - 1); |
| 65 | vp = ep; |
| 66 | } else { /* plain $x */ |
| 67 | SKIP(vp, ep, ACL_ISALNUM(*ep) || *ep == '_'); |
| 68 | acl_vstring_strncat(buf, vp, ep - vp); |
| 69 | vp = ep; |
| 70 | } |
| 71 | if (ACL_VSTRING_LEN(buf) == 0) { |
| 72 | status |= MAC_PARSE_ERROR; |
| 73 | acl_msg_warn("empty macro name: \"%s\"", value); |
| 74 | break; |
| 75 | } |
| 76 | MAC_PARSE_ACTION(status, MAC_PARSE_EXPR, buf, context); |
no test coverage detected
searching dependent graphs…