static int mac_expand_callback(int type, VSTRING *buf, char *ptr) { char *myname = "mac_expand_callback"; MAC_EXP *mc = (MAC_EXP *) ptr; int lookup_mode; const char *text; char *cp; int ch; int len; /* * Sanity check. */ if (mc->level++ > 100) { msg_warn("unreasonable macro call nesting: \"%s\"", vstring_str(buf)); mc->status |= MAC_PARSE_ERROR; } if (mc->status & MAC_PARSE_ERROR) return (mc->status); /* * $Name etc. reference. */ if (type == MAC_PARSE_VARNAME) { /* * Look for the ? or : delimiter. In case of a syntax error, return * without doing damage, and issue a warning instead. */ for (cp = vstring_str(buf); /* void */ ; cp++) { if ((ch = *cp) == 0) { lookup_mode = MAC_EXP_MODE_USE; break; } if (ch == '?' || ch == ':') { *cp++ = 0; lookup_mode = MAC_EXP_MODE_TEST; break; } if (!ISALNUM(ch) && ch != '_') { msg_warn("macro name syntax error: \"%s\"", vstring_str(buf)); mc->status |= MAC_PARSE_ERROR; return (mc->status); } } /* * Look up the named parameter. */ text = mc->lookup(vstring_str(buf), lookup_mode, mc->context); /* * Perform the requested substitution. */ switch (ch) { case '?': if (text != 0 && *text != 0) mac_parse(cp, mac_expand_callback, (char *) mc); break; case ':': if (text == 0 || *text == 0) mac_parse(cp, mac_expand_callback, (char *) mc); break; default: if (text == 0) { mc->status |= MAC_PARSE_UNDEF; } else if (*text == 0) { /* void */ ; } else if (mc->flags & MAC_EXP_FLAG_RECURSE) { mac_parse(text, mac_expand_callback, (char *) mc); } else { len = VSTRING_LEN(mc->result); vstring_strcat(mc->result, text); if (mc->filter) { cp = vstring_str(mc->result) + len; while (*(cp += strspn(cp, mc->filter))) *cp++ = '_'; } } break; } } /* * Literal text. */ else { text = vstring_str(buf); vstring_strcat(mc->result, text); } /* * Give the poor tester a clue of what is going on. */ if (msg_verbose) msg_info("%s: %s = %s", myname, vstring_str(buf), text ? text : "(undef)"); mc->level--; return (mc->status); }
static int mac_expand_callback(int type, VSTRING *buf, char *ptr) { MAC_EXP *mc = (MAC_EXP *) ptr; int lookup_mode; const char *text; char *cp; int ch; ssize_t len; /* * Sanity check. */ if (mc->level++ > 100) { msg_warn("unreasonable macro call nesting: \"%s\"", vstring_str(buf)); mc->status |= MAC_PARSE_ERROR; } if (mc->status & MAC_PARSE_ERROR) return (mc->status); /* * $Name etc. reference. * * In order to support expansion of lookup results, we must save the lookup * result. We use the input buffer since it will not be needed anymore. */ if (type == MAC_PARSE_EXPR) { /* * Look for the ? or : delimiter. In case of a syntax error, return * without doing damage, and issue a warning instead. */ for (cp = vstring_str(buf); /* void */ ; cp++) { if ((ch = *cp) == 0) { lookup_mode = MAC_EXP_MODE_USE; break; } if (ch == '?' || ch == ':') { *cp++ = 0; lookup_mode = MAC_EXP_MODE_TEST; break; } if (!ISALNUM(ch) && ch != '_') { msg_warn("macro name syntax error: \"%s\"", vstring_str(buf)); mc->status |= MAC_PARSE_ERROR; return (mc->status); } } /* * Look up the named parameter. */ text = mc->lookup(vstring_str(buf), lookup_mode, mc->context); /* * Perform the requested substitution. */ switch (ch) { case '?': if ((text != 0 && *text != 0) || (mc->flags & MAC_EXP_FLAG_SCAN)) mac_parse(cp, mac_expand_callback, (char *) mc); break; case ':': if (text == 0 || *text == 0 || (mc->flags & MAC_EXP_FLAG_SCAN)) mac_parse(cp, mac_expand_callback, (char *) mc); break; default: if (text == 0) { mc->status |= MAC_PARSE_UNDEF; } else if (*text == 0 || (mc->flags & MAC_EXP_FLAG_SCAN)) { /* void */ ; } else if (mc->flags & MAC_EXP_FLAG_RECURSE) { vstring_strcpy(buf, text); mac_parse(vstring_str(buf), mac_expand_callback, (char *) mc); } else { len = VSTRING_LEN(mc->result); vstring_strcat(mc->result, text); if (mc->filter) { cp = vstring_str(mc->result) + len; while (*(cp += strspn(cp, mc->filter))) *cp++ = '_'; } } break; } } /* * Literal text. */ else if ((mc->flags & MAC_EXP_FLAG_SCAN) == 0) { vstring_strcat(mc->result, vstring_str(buf)); } mc->level--; return (mc->status); }