summaryrefslogtreecommitdiffstats
path: root/lib/libutil/property.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil/property.c')
-rw-r--r--lib/libutil/property.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/lib/libutil/property.c b/lib/libutil/property.c
new file mode 100644
index 0000000..3a1b991
--- /dev/null
+++ b/lib/libutil/property.c
@@ -0,0 +1,215 @@
+/*
+ *
+ * Simple property list handling code.
+ *
+ * Copyright (c) 1998
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libutil.h>
+
+#define MAX_NAME 64
+#define MAX_VALUE 512
+
+static properties
+property_alloc(char *name, char *value)
+{
+ properties n;
+
+ n = (properties)malloc(sizeof(struct _property));
+ n->next = NULL;
+ n->name = name ? strdup(name) : NULL;
+ n->value = value ? strdup(value) : NULL;
+ return n;
+}
+
+properties
+properties_read(FILE *fp)
+{
+ properties head, ptr;
+ char hold_n[MAX_NAME + 1];
+ char hold_v[MAX_VALUE + 1];
+ char buf[BUFSIZ * 4];
+ int bp, n, v, max;
+ enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state;
+ int ch = 0;
+
+ n = v = bp = max = 0;
+ head = ptr = NULL;
+ state = LOOK;
+ while (state != STOP) {
+ if (state != COMMIT) {
+ if (bp == max)
+ state = FILL;
+ else
+ ch = buf[bp++];
+ }
+ switch(state) {
+ case FILL:
+ if ((max = fread(buf, 1, sizeof buf, fp)) <= 0) {
+ state = STOP;
+ break;
+ }
+ else {
+ state = LOOK;
+ ch = buf[0];
+ bp = 1;
+ }
+ /* Fall through deliberately since we already have a character and state == LOOK */
+
+ case LOOK:
+ if (isspace(ch))
+ continue;
+ /* Allow shell or lisp style comments */
+ else if (ch == '#' || ch == ';') {
+ state = COMMENT;
+ continue;
+ }
+ else if (isalnum(ch) || ch == '_') {
+ if (n >= MAX_NAME) {
+ n = 0;
+ state = COMMENT;
+ }
+ else {
+ hold_n[n++] = ch;
+ state = NAME;
+ }
+ }
+ else
+ state = COMMENT; /* Ignore the rest of the line */
+ break;
+
+ case COMMENT:
+ if (ch == '\n')
+ state = LOOK;
+ break;
+
+ case NAME:
+ if (ch == '\n' || !ch) {
+ hold_n[n] = '\0';
+ hold_v[0] = '\0';
+ v = n = 0;
+ state = COMMIT;
+ }
+ else if (isspace(ch))
+ continue;
+ else if (ch == '=') {
+ hold_n[n] = '\0';
+ v = n = 0;
+ state = VALUE;
+ }
+ else
+ hold_n[n++] = ch;
+ break;
+
+ case VALUE:
+ if (v == 0 && isspace(ch))
+ continue;
+ else if (ch == '{')
+ state = MVALUE;
+ else if (ch == '\n' || !ch) {
+ hold_v[v] = '\0';
+ v = n = 0;
+ state = COMMIT;
+ }
+ else {
+ if (v >= MAX_VALUE) {
+ state = COMMENT;
+ v = n = 0;
+ break;
+ }
+ else
+ hold_v[v++] = ch;
+ }
+ break;
+
+ case MVALUE:
+ /* multiline value */
+ if (v >= MAX_VALUE) {
+ state = COMMENT;
+ n = v = 0;
+ }
+ else if (ch == '}') {
+ hold_v[v] = '\0';
+ v = n = 0;
+ state = COMMIT;
+ }
+ else
+ hold_v[v++] = ch;
+ break;
+
+ case COMMIT:
+ if (!head)
+ head = ptr = property_alloc(hold_n, hold_v);
+ else {
+ ptr->next = property_alloc(hold_n, hold_v);
+ ptr = ptr->next;
+ }
+ state = LOOK;
+ v = n = 0;
+ break;
+
+ case STOP:
+ /* we don't handle this here, but this prevents warnings */
+ break;
+ }
+ }
+ return head;
+}
+
+char *
+property_find(properties list, const char *name)
+{
+ if (!list || !name || !name[0])
+ return NULL;
+ while (list) {
+ if (!strcmp(list->name, name))
+ return list->value;
+ list = list->next;
+ }
+ return NULL;
+}
+
+void
+properties_free(properties list)
+{
+ properties tmp;
+
+ while (list) {
+ tmp = list->next;
+ if (list->name)
+ free(list->name);
+ if (list->value)
+ free(list->value);
+ free(list);
+ list = tmp;
+ }
+}
+
OpenPOWER on IntegriCloud