arm: rmobile: kzm9g: Adjust SDRAM setting
[platform/kernel/u-boot.git] / lib / hashtable.c
index 6861a42..07ebfb2 100644 (file)
@@ -54,7 +54,9 @@
 #define        CONFIG_ENV_MAX_ENTRIES 512
 #endif
 
-#include "search.h"
+#include <env_callback.h>
+#include <env_flags.h>
+#include <search.h>
 
 /*
  * [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
@@ -274,6 +276,17 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
                                return 0;
                        }
 
+                       /* If there is a callback, call it */
+                       if (htab->table[idx].entry.callback &&
+                           htab->table[idx].entry.callback(item.key,
+                           item.data, env_op_overwrite, flag)) {
+                               debug("callback() rejected setting variable "
+                                       "%s, skipping it!\n", item.key);
+                               __set_errno(EINVAL);
+                               *retval = NULL;
+                               return 0;
+                       }
+
                        free(htab->table[idx].entry.data);
                        htab->table[idx].entry.data = strdup(item.data);
                        if (!htab->table[idx].entry.data) {
@@ -398,6 +411,11 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
 
                ++htab->filled;
 
+               /* This is a new entry, so look up a possible callback */
+               env_callback_init(&htab->table[idx].entry);
+               /* Also look for flags */
+               env_flags_init(&htab->table[idx].entry);
+
                /* check for permission */
                if (htab->change_ok != NULL && htab->change_ok(
                    &htab->table[idx].entry, item.data, env_op_create, flag)) {
@@ -409,6 +427,18 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
                        return 0;
                }
 
+               /* If there is a callback, call it */
+               if (htab->table[idx].entry.callback &&
+                   htab->table[idx].entry.callback(item.key, item.data,
+                   env_op_create, flag)) {
+                       debug("callback() rejected setting variable "
+                               "%s, skipping it!\n", item.key);
+                       _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+                       __set_errno(EINVAL);
+                       *retval = NULL;
+                       return 0;
+               }
+
                /* return new entry */
                *retval = &htab->table[idx].entry;
                return 1;
@@ -437,6 +467,8 @@ static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
        debug("hdelete: DELETING key \"%s\"\n", key);
        free((void *)ep->key);
        free(ep->data);
+       ep->callback = NULL;
+       ep->flags = 0;
        htab->table[idx].used = -1;
 
        --htab->filled;
@@ -466,6 +498,15 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
                return 0;
        }
 
+       /* If there is a callback, call it */
+       if (htab->table[idx].entry.callback &&
+           htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
+               debug("callback() rejected deleting variable "
+                       "%s, skipping it!\n", key);
+               __set_errno(EINVAL);
+               return 0;
+       }
+
        _hdelete(key, htab, ep, idx);
 
        return 1;
@@ -522,7 +563,7 @@ static int cmpkey(const void *p1, const void *p2)
        return (strcmp(e1->key, e2->key));
 }
 
-ssize_t hexport_r(struct hsearch_data *htab, const char sep,
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
                 char **resp, size_t size,
                 int argc, char * const argv[])
 {
@@ -559,6 +600,9 @@ ssize_t hexport_r(struct hsearch_data *htab, const char sep,
                        if ((argc > 0) && (found == 0))
                                continue;
 
+                       if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
+                               continue;
+
                        list[n++] = ep;
 
                        totlen += strlen(ep->key) + 2;
@@ -835,11 +879,9 @@ int himport_r(struct hsearch_data *htab,
                e.data = value;
 
                hsearch_r(e, ENTER, &rv, htab, flag);
-               if (rv == NULL) {
+               if (rv == NULL)
                        printf("himport_r: can't insert \"%s=%s\" into hash table\n",
                                name, value);
-                       return 0;
-               }
 
                debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
                        htab, htab->filled, htab->size,
@@ -870,3 +912,27 @@ int himport_r(struct hsearch_data *htab,
        debug("INSERT: done\n");
        return 1;               /* everything OK */
 }
+
+/*
+ * hwalk_r()
+ */
+
+/*
+ * Walk all of the entries in the hash, calling the callback for each one.
+ * this allows some generic operation to be performed on each element.
+ */
+int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *))
+{
+       int i;
+       int retval;
+
+       for (i = 1; i <= htab->size; ++i) {
+               if (htab->table[i].used > 0) {
+                       retval = callback(&htab->table[i].entry);
+                       if (retval)
+                               return retval;
+               }
+       }
+
+       return 0;
+}