const char *dict_eval(const char *dict_name, const char *value, int recursive) { const char *myname = "dict_eval"; static VSTRING *buf; int status; /* * Initialize. */ if (buf == 0) buf = vstring_alloc(10); /* * Expand macros, possibly recursively. */ #define DONT_FILTER (char *) 0 status = mac_expand(buf, value, recursive ? MAC_EXP_FLAG_RECURSE : MAC_EXP_FLAG_NONE, DONT_FILTER, dict_eval_lookup, (char *) dict_name); if (status & MAC_PARSE_ERROR) msg_fatal("dictionary %s: macro processing error", dict_name); if (msg_verbose > 1) { if (strcmp(value, STR(buf)) != 0) msg_info("%s: expand %s -> %s", myname, value, STR(buf)); else msg_info("%s: const %s", myname, value); } return (STR(buf)); }
int main(int unused_argc, char **unused_argv) { VSTRING *buf = vstring_alloc(100); VSTRING *result = vstring_alloc(100); char *cp; char *name; char *value; HTABLE *table; int stat; while (!vstream_feof(VSTREAM_IN)) { table = htable_create(0); /* * Read a block of definitions, terminated with an empty line. */ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { vstream_printf("<< %s\n", vstring_str(buf)); vstream_fflush(VSTREAM_OUT); if (VSTRING_LEN(buf) == 0) break; cp = vstring_str(buf); name = mystrtok(&cp, " \t\r\n="); value = mystrtok(&cp, " \t\r\n="); htable_enter(table, name, value ? mystrdup(value) : 0); } /* * Read a block of patterns, terminated with an empty line or EOF. */ while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { vstream_printf("<< %s\n", vstring_str(buf)); vstream_fflush(VSTREAM_OUT); if (VSTRING_LEN(buf) == 0) break; cp = vstring_str(buf); VSTRING_RESET(result); stat = mac_expand(result, vstring_str(buf), MAC_EXP_FLAG_NONE, (char *) 0, lookup, (char *) table); vstream_printf("stat=%d result=%s\n", stat, vstring_str(result)); vstream_fflush(VSTREAM_OUT); } htable_free(table, myfree); vstream_printf("\n"); } /* * Clean up. */ vstring_free(buf); vstring_free(result); exit(0); }
int local_expand(VSTRING *result, const char *pattern, LOCAL_STATE *state, USER_ATTR *usr_attr, const char *filter) { LOCAL_EXP local; int expand_status; local.state = state; local.usr_attr = usr_attr; local.status = 0; expand_status = mac_expand(result, pattern, MAC_EXP_FLAG_NONE, filter, local_expand_lookup, (char *) &local); return (local.status | expand_status); }
char *pcf_expand_parameter_value(VSTRING *buf, int mode, const char *value, PCF_MASTER_ENT *local_scope) { const char *myname = "pcf_expand_parameter_value"; static VSTRING *local_buf; int status; PCF_EVAL_CTX eval_ctx; /* * Initialize. */ if (buf == 0) { if (local_buf == 0) local_buf = vstring_alloc(10); buf = local_buf; } /* * Expand macros recursively. * * When expanding $name in "postconf -n" parameter values, don't limit the * search to only non-default parameter values. * * When expanding $name in "postconf -d" parameter values, do limit the * search to only default parameter values. */ #define DONT_FILTER (char *) 0 eval_ctx.mode = (mode & ~PCF_SHOW_NONDEF); eval_ctx.local_scope = local_scope; status = mac_expand(buf, value, MAC_EXP_FLAG_RECURSE, DONT_FILTER, pcf_lookup_parameter_value_wrapper, (void *) &eval_ctx); if (status & MAC_PARSE_ERROR) msg_fatal("macro processing error"); if (msg_verbose > 1) { if (strcmp(value, STR(buf)) != 0) msg_info("%s: expand %s -> %s", myname, value, STR(buf)); else msg_info("%s: const %s", myname, value); } return (STR(buf)); }
void register_dbms_parameters(const char *param_value, const char *(flag_parameter) (const char *, int, char *), PC_MASTER_ENT *local_scope) { const PC_DBMS_INFO *dp; char *bufp; char *db_type; char *prefix; static VSTRING *buffer = 0; static VSTRING *candidate = 0; const char **cpp; /* * Emulate Postfix parameter value expansion, prepending the appropriate * local (master.cf "-o name-value") namespace to the global (main.cf * "name=value") namespace. * * XXX This does not examine both sides of conditional macro expansion, and * may expand the "wrong" conditional macros. This is the best we can do * for legacy database configuration support. */ #define NO_SCAN_FILTER ((char *) 0) (void) mac_expand(buffer ? buffer : (buffer = vstring_alloc(100)), param_value, MAC_EXP_FLAG_RECURSE, NO_SCAN_FILTER, register_dbms_parameters_cb, (char *) local_scope); /* * Naive parsing. We don't really know if the parameter specifies free * text or a list of databases. */ bufp = STR(buffer); while ((db_type = mystrtok(&bufp, " ,\t\r\n")) != 0) { /* * Skip over "proxy:" indirections. */ while ((prefix = split_at(db_type, ':')) != 0 && strcmp(db_type, DICT_TYPE_PROXY) == 0) db_type = prefix; /* * Look for database:prefix where the prefix is not a pathname and * the database is a known type. Synthesize candidate parameter names * from the user-defined prefix and from the database-defined suffix * list, and see if those parameters have a "name=value" entry in the * local or global namespace. */ if (prefix != 0 && *prefix != '/' && *prefix != '.') { for (dp = dbms_info; dp->db_type != 0; dp++) { if (strcmp(db_type, dp->db_type) == 0) { for (cpp = dp->db_suffixes; *cpp; cpp++) { vstring_sprintf(candidate ? candidate : (candidate = vstring_alloc(30)), "%s_%s", prefix, *cpp); flag_parameter(STR(candidate), 0, (char *) local_scope); } break; } } } } }
static int mac_exp_parse_relational(MAC_EXP_CONTEXT *mc, const char **lookup, char **bp) { char *cp = *bp; VSTRING *left_op_buf; VSTRING *rite_op_buf; const char *left_op_strval; const char *rite_op_strval; char *op_pos; char *op_strval; size_t op_len; int op_tokval; int op_result; size_t tmp_len; /* * Left operand. The caller is expected to skip leading whitespace before * the {. See MAC_EXP_FIND_LEFT_CURLY(). */ if ((left_op_strval = mac_exp_extract_curly_payload(mc, &cp)) == 0) return (mc->status); /* * Operator. Todo: regexp operator. */ op_pos = cp; op_len = strspn(cp, "<>!=?+-*/~&|%"); /* for better diagnostics. */ op_strval = mystrndup(cp, op_len); op_tokval = name_code(mac_exp_op_table, NAME_CODE_FLAG_NONE, op_strval); myfree(op_strval); if (op_tokval == MAC_EXP_OP_TOK_NONE) MAC_EXP_ERR_RETURN(mc, "%s expected at: \"...%s}>>>%.20s\"", MAC_EXP_OP_STR_ANY, left_op_strval, cp); cp += op_len; /* * Right operand. Todo: syntax may depend on operator. */ if (MAC_EXP_FIND_LEFT_CURLY(tmp_len, cp) == 0) MAC_EXP_ERR_RETURN(mc, "\"{expression}\" expected at: " "\"...{%s} %.*s>>>%.20s\"", left_op_strval, (int) op_len, op_pos, cp); if ((rite_op_strval = mac_exp_extract_curly_payload(mc, &cp)) == 0) return (mc->status); /* * Evaluate the relational expression. Todo: regexp support. */ mc->status |= mac_expand(left_op_buf = vstring_alloc(100), left_op_strval, mc->flags, mc->filter, mc->lookup, mc->context); mc->status |= mac_expand(rite_op_buf = vstring_alloc(100), rite_op_strval, mc->flags, mc->filter, mc->lookup, mc->context); op_result = mac_exp_eval(vstring_str(left_op_buf), op_tokval, vstring_str(rite_op_buf)); vstring_free(left_op_buf); vstring_free(rite_op_buf); if (mc->status & MAC_PARSE_ERROR) return (mc->status); /* * Here, we fake up a non-empty or empty parameter value lookup result, * for compatibility with the historical code that looks named parameter * values. */ *lookup = (op_result ? MAC_EXP_BVAL_TRUE : MAC_EXP_BVAL_FALSE); *bp = cp; return (0); }