summaryrefslogtreecommitdiffstats
path: root/src/pattern.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pattern.c')
-rw-r--r--src/pattern.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/src/pattern.c b/src/pattern.c
index 52dda5e..f07223f 100644
--- a/src/pattern.c
+++ b/src/pattern.c
@@ -1547,6 +1547,10 @@ struct pat_ref *pat_ref_lookup(const char *reference)
{
struct pat_ref *ref;
+ /* Skip file@ prefix, it is the default case. Can be mixed with ref omitting the prefix */
+ if (strlen(reference) > 5 && strncmp(reference, "file@", 5) == 0)
+ reference += 5;
+
list_for_each_entry(ref, &pattern_reference, list)
if (ref->reference && strcmp(reference, ref->reference) == 0)
return ref;
@@ -1834,6 +1838,22 @@ struct pat_ref *pat_ref_new(const char *reference, const char *display, unsigned
}
}
+
+ if (strlen(reference) > 5 && strncmp(reference, "virt@", 5) == 0)
+ flags |= PAT_REF_ID;
+ else if (strlen(reference) > 4 && strncmp(reference, "opt@", 4) == 0) {
+ flags |= (PAT_REF_ID|PAT_REF_FILE); // Will be decided later
+ reference += 4;
+ }
+ else {
+ /* A file by default */
+ flags |= PAT_REF_FILE;
+ /* Skip file@ prefix to be mixed with ref omitting the prefix */
+ if (strlen(reference) > 5 && strncmp(reference, "file@", 5) == 0)
+ reference += 5;
+ }
+
+
ref->reference = strdup(reference);
if (!ref->reference) {
free(ref->display);
@@ -2239,7 +2259,7 @@ struct pattern_expr *pattern_new_expr(struct pattern_head *head, struct pat_ref
*
* Return non-zero in case of success, otherwise 0.
*/
-int pat_ref_read_from_file_smp(struct pat_ref *ref, const char *filename, char **err)
+int pat_ref_read_from_file_smp(struct pat_ref *ref, char **err)
{
FILE *file;
char *c;
@@ -2250,11 +2270,17 @@ int pat_ref_read_from_file_smp(struct pat_ref *ref, const char *filename, char *
char *value_beg;
char *value_end;
- file = fopen(filename, "r");
+ file = fopen(ref->reference, "r");
if (!file) {
- memprintf(err, "failed to open pattern file <%s>", filename);
+ if (ref->flags & PAT_REF_ID) {
+ /* file not found for an optional file, switch it to a virtual list of patterns */
+ ref->flags &= ~PAT_REF_FILE;
+ return 1;
+ }
+ memprintf(err, "failed to open pattern file <%s>", ref->reference);
return 0;
}
+ ref->flags |= PAT_REF_FILE;
/* now parse all patterns. The file may contain only one pattern
* followed by one value per line. The start spaces, separator spaces
@@ -2310,7 +2336,7 @@ int pat_ref_read_from_file_smp(struct pat_ref *ref, const char *filename, char *
if (ferror(file)) {
memprintf(err, "error encountered while reading <%s> : %s",
- filename, strerror(errno));
+ ref->reference, strerror(errno));
goto out_close;
}
/* success */
@@ -2324,7 +2350,7 @@ int pat_ref_read_from_file_smp(struct pat_ref *ref, const char *filename, char *
/* Reads patterns from a file. If <err_msg> is non-NULL, an error message will
* be returned there on errors and the caller will have to free it.
*/
-int pat_ref_read_from_file(struct pat_ref *ref, const char *filename, char **err)
+int pat_ref_read_from_file(struct pat_ref *ref, char **err)
{
FILE *file;
char *c;
@@ -2332,9 +2358,14 @@ int pat_ref_read_from_file(struct pat_ref *ref, const char *filename, char **err
int ret = 0;
int line = 0;
- file = fopen(filename, "r");
+ file = fopen(ref->reference, "r");
if (!file) {
- memprintf(err, "failed to open pattern file <%s>", filename);
+ if (ref->flags & PAT_REF_ID) {
+ /* file not found for an optional file, switch it to a virtual list of patterns */
+ ref->flags &= ~PAT_REF_FILE;
+ return 1;
+ }
+ memprintf(err, "failed to open pattern file <%s>", ref->reference);
return 0;
}
@@ -2365,14 +2396,14 @@ int pat_ref_read_from_file(struct pat_ref *ref, const char *filename, char **err
continue;
if (!pat_ref_append(ref, arg, NULL, line)) {
- memprintf(err, "out of memory when loading patterns from file <%s>", filename);
+ memprintf(err, "out of memory when loading patterns from file <%s>", ref->reference);
goto out_close;
}
}
if (ferror(file)) {
memprintf(err, "error encountered while reading <%s> : %s",
- filename, strerror(errno));
+ ref->reference, strerror(errno));
goto out_close;
}
ret = 1; /* success */
@@ -2406,14 +2437,16 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
return 0;
}
- if (load_smp) {
- ref->flags |= PAT_REF_SMP;
- if (!pat_ref_read_from_file_smp(ref, filename, err))
- return 0;
- }
- else {
- if (!pat_ref_read_from_file(ref, filename, err))
- return 0;
+ if (ref->flags & PAT_REF_FILE) {
+ if (load_smp) {
+ ref->flags |= PAT_REF_SMP;
+ if (!pat_ref_read_from_file_smp(ref, err))
+ return 0;
+ }
+ else {
+ if (!pat_ref_read_from_file(ref, err))
+ return 0;
+ }
}
}
else {
@@ -2479,7 +2512,10 @@ int pattern_read_from_file(struct pattern_head *head, unsigned int refflags,
/* Load reference content in the pattern expression.
* We need to load elements in the same order they were seen in the
- * file as list-based matching types may rely on it.
+ * file. Indeed, some list-based matching types may rely on it as the
+ * list is positional, and for tree-based matching, even if the tree is
+ * content-based in case of duplicated keys we only want the first key
+ * in the file to be considered.
*/
list_for_each_entry(elt, &ref->head, list) {
if (!pat_ref_push(elt, expr, patflags, err)) {