/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* thisisamacro:name,arguments,contents,location.
*/ typedefstruct
{ char *name; /* lower case name of the macro */
apr_array_header_t *arguments; /* of char*, macro parameter names */
apr_array_header_t *contents; /* of char*, macro body */ char *location; /* of macro definition, for error messages */
} ap_macro_t;
/* generatesanerroronmacrowithtwoargumentsofthesamename. generatesanerrorifamacroargumentnameisempty. generatesawarningifargumentsnameprefixesconflict. generatesawarningifthefirstcharofanargumentisnotinARG_PREFIX
*/ staticconstchar *check_macro_arguments(apr_pool_t * pool, const ap_macro_t * macro)
{ char **tab = (char **) macro->arguments->elts; int nelts = macro->arguments->nelts; int i;
for (i = 0; i < nelts; i++) {
size_t ltabi = strlen(tab[i]); int j;
if (ltabi == 0) { return apr_psprintf(pool, "macro '%s' (%s): empty argument #%d name",
macro->name, macro->location, i + 1);
} elseif (!looks_like_an_argument(tab[i])) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02796) "macro '%s' (%s) " "argument name '%s' (#%d) without expected prefix, " "better prefix argument names with one of '%s'.",
macro->name, macro->location,
tab[i], i + 1, ARG_PREFIX);
}
for (j = i + 1; j < nelts; j++) {
size_t ltabj = strlen(tab[j]);
/* must not use the same argument name twice */ if (!strcmp(tab[i], tab[j])) { return apr_psprintf(pool, "argument name conflict in macro '%s' (%s): " "argument '%s': #%d and #%d, " "change argument names!",
macro->name, macro->location,
tab[i], i + 1, j + 1);
}
/* warn about common prefix, but only if non empty names */ if (ltabi && ltabj &&
!strncmp(tab[i], tab[j], ltabi < ltabj ? ltabi : ltabj)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02797) "macro '%s' (%s): " "argument name prefix conflict (%s #%d and %s #%d), " "be careful about your macro definition!",
macro->name, macro->location,
tab[i], i + 1, tab[j], j + 1);
}
}
}
return NULL;
}
/* warnaboutemptystringsinarray.couldbelegitimate.
*/ staticvoid check_macro_use_arguments(constchar *where, const apr_array_header_t * array)
{ char **tab = (char **) array->elts; int i; for (i = 0; i < array->nelts; i++) { if (empty_string_p(tab[i])) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02798) "%s: empty argument #%d", where, i + 1);
}
}
}
if (result) {
*result = apr_array_make(pool, contents->nelts, sizeof(char *));
}
/* for each line of the macro body */ for (i = 0; i < contents->nelts; i++) { constchar *errmsg; /* copy the line and substitute macro parameters */
apr_cpystrn(line, ((char **) contents->elts)[i], MAX_STRING_LEN);
errmsg = substitute_macro_args(line, MAX_STRING_LEN,
macro, replacements, used); if (errmsg) { return apr_psprintf(pool, "while processing line %d of macro '%s' (%s) %s",
i + 1, macro->name, macro->location, errmsg);
} /* append substituted line to result array */ if (result) { char **new = apr_array_push(*result);
*new = apr_pstrdup(pool, line);
}
}
return NULL;
}
/* warnifsomemacroargumentsarenotused.
*/ staticconstchar *check_macro_contents(apr_pool_t * pool, const ap_macro_t * macro)
{ int nelts = macro->arguments->nelts; char **names = (char **) macro->arguments->elts;
apr_array_header_t *used; int i; constchar *errmsg;
if (macro->contents->nelts == 0) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02799) "macro '%s' (%s): empty contents!",
macro->name, macro->location); return NULL; /* no need to further warnings... */
}
used = apr_array_make(pool, nelts, sizeof(char));
for (i = 0; i < nelts; i++) {
used->elts[i] = 0;
}
Thereissomehopus-pocustodealwithline_numberwhentransitingfrom oneconfigtotheother.
*/ typedefstruct
{ int index; /* current element */ int char_index; /* current char in element */ int length; /* cached length of the current line */
apr_array_header_t *contents; /* array of char * */
ap_configfile_t *next; /* next config once this one is processed */
ap_configfile_t **upper; /* hack: where to update it if needed */
} array_contents_t;
/* read chars from stream, stop on newline */ while (i < bufsize - 1 && next != LF &&
((rc = array_getch(&next, param)) == APR_SUCCESS)) {
buffer[i++] = next;
}
if (rc == APR_EOF) { /* maybe update to next, possibly a recursion */ if (next_one(ml)) {
ap_assert(ml->next->getstr); /* keep next line count in sync! the caller will update
the current line_number, we need to forward to the next */
ml->next->line_number++; return ml->next->getstr(buf, bufsize, ml->next->param);
} /* else that is really all we can do */ return APR_EOF;
}
buffer[i] = '\0';
return APR_SUCCESS;
}
/* closethearraystream?
*/ static apr_status_t array_close(void *param)
{
array_contents_t *ml = (array_contents_t *) param; /* move index at end of stream... */
ml->index = ml->contents->nelts;
ml->char_index = ml->length; return APR_SUCCESS;
}
warn_if_non_blank(APLOGNO(02801) "non blank chars found after "
BEGIN_MACRO " closing '>'",
endp+1, cmd->config_file);
/* coldly drop '>[^>]*$' out */
*endp = '\0';
/* get lowercase macro name */
name = ap_getword_conf(pool, &arg); if (empty_string_p(name)) { return BEGIN_MACRO " macro definition: name not found";
}
/* get macro arguments */
macro->location = apr_psprintf(pool, "defined on line %d of \"%s\"",
cmd->config_file->line_number,
cmd->config_file->name);
debug(fprintf(stderr, "macro_section: location=%s\n", macro->location));
where =
apr_psprintf(pool, "macro '%s' (%s)", macro->name, macro->location);
if (looks_like_an_argument(name)) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(02803) "%s better prefix a macro name with any of '%s'",
where, ARG_PREFIX);
}
/* get macro parameters */
macro->arguments = get_arguments(pool, arg);
/* must be initialized, or no macros has been defined */ if (ap_macros == NULL) { return"no macro defined before " USE_MACRO;
}
/* get lowercase macro name */
name = ap_getword_conf(cmd->temp_pool, &arg);
ap_str_tolower(name);
if (empty_string_p(name)) { return"no macro name specified with " USE_MACRO;
}
/* get macro definition */
macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING);
if (!macro) { return apr_psprintf(cmd->temp_pool, "macro '%s' undefined", name);
}
/* recursion is detected here by looking at the config file name, *whichmayalreadycontains"macro'foo'".Ok,itlookslikeahack, *butotherwiseitisuneasytokeepthisdataavailablesomewhere... *thenamehasjusttheneededvisibilityandliveness.
*/
recursion =
apr_pstrcat(cmd->temp_pool, "macro '", macro->name, "'", NULL);
if (ap_strstr((char *) cmd->config_file->name, recursion)) { return apr_psprintf(cmd->temp_pool, "recursive use of macro '%s' is invalid",
macro->name);
}
/* get macro arguments */
replacements = get_arguments(cmd->temp_pool, arg);
if (macro->arguments->nelts != replacements->nelts) { return apr_psprintf(cmd->temp_pool, "macro '%s' (%s) used " "with %d arguments instead of %d",
macro->name, macro->location,
replacements->nelts, macro->arguments->nelts);
}
where = apr_psprintf(cmd->temp_pool, "macro '%s' (%s) used on line %d of \"%s\"",
macro->name, macro->location,
cmd->config_file->line_number,
cmd->config_file->name);
if (errmsg) { return apr_psprintf(cmd->temp_pool, "%s error while substituting: %s",
where, errmsg);
}
/* the current "config file" is replaced by a string array... attheendofprocessingthearray,theinitialconfigfile
will be returned there (see next_one) so as to go on. */
cmd->config_file = make_array_config(cmd->temp_pool, contents, where,
cmd->config_file, &cmd->config_file);
/* must be initialized, or no macros has been defined */ if (ap_macros == NULL) { return"no macro defined before " UNDEF_MACRO;
}
if (empty_string_p(arg)) { return"no macro name specified with " UNDEF_MACRO;
}
/* check that the macro is defined */
name = apr_pstrdup(cmd->temp_pool, arg);
ap_str_tolower(name);
macro = apr_hash_get(ap_macros, name, APR_HASH_KEY_STRING); if (macro == NULL) { /* could be a warning? */ return apr_psprintf(cmd->temp_pool, "cannot remove undefined macro '%s'", name);
}
/* free macro: cannot do that */ /* remove macro from hash table */
apr_hash_set(ap_macros, name, APR_HASH_KEY_STRING, NULL);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.