+ char **tmp = nmem_malloc(nmem, dictionary->size * 2 * sizeof(char*));
+ memcpy(tmp, dictionary->dict, dictionary->size * sizeof(char*));
+ dictionary->dict = tmp;
+ dictionary->size *= 2;
+ }
+ dictionary->dict[dictionary->num++] = nmem_strdup(nmem, set->name);
+}
+
+// This is called from grep_databases -- adds/overrides setting for a target
+// This is also where the rules for precedence of settings are implemented
+static void update_database(void *context, struct database *db)
+{
+ struct setting *set = (struct setting *) context;
+ struct setting *s, **sp;
+ int offset;
+
+ // Is this the right database?
+ if (!match_zurl(db->url, set->target))
+ return;
+
+ // Initialize settings array if it doesn't exist.
+ // If so, also set the 'id' automatic setting
+ if (!db->settings)
+ {
+ struct setting *id = nmem_malloc(nmem, sizeof(struct setting));
+
+ db->settings = nmem_malloc(nmem, sizeof(struct settings*) * dictionary->num);
+ memset(db->settings, 0, sizeof(struct settings*) * dictionary->num);
+ id->precedence = 0;
+ id->name = "pz:id";
+ id->target = id->value = db->url;
+ id->next = 0;
+ db->settings[PZ_ID] = id;
+ }
+ if ((offset = settings_offset_cprefix(set->name)) < 0)
+ abort(); // Should never get here
+
+ // First we determine if this setting is overriding any existing settings
+ // with the same name.
+ for (s = db->settings[offset], sp = &db->settings[offset]; s;
+ sp = &s->next, s = s->next)
+ if (!strcmp(s->name, set->name))
+ {
+ if (s->precedence < set->precedence)
+ // We discard the value (nmem keeps track of the space)
+ *sp = (*sp)->next;
+ else if (s->precedence > set->precedence)
+ // Db contains a higher-priority setting. Abort
+ break;
+ if (*s->target == '*' && *set->target != '*')
+ // target-specific value trumps wildcard. Delete.
+ *sp = (*sp)->next;
+ else if (*s->target != '*' && *set->target == '*')
+ // Db already contains higher-priority setting. Abort
+ break;
+ }
+ if (!s) // s will be null when there are no higher-priority settings -- we add one
+ {
+ struct setting *new = nmem_malloc(nmem, sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+ new->precedence = set->precedence;
+ new->target = nmem_strdup(nmem, set->target);
+ new->name = nmem_strdup(nmem, set->name);
+ new->value = nmem_strdup(nmem, set->value);
+ new->next = db->settings[offset];
+ db->settings[offset] = new;