property.c revision 40040
1/* 2 * 3 * Simple property list handling code. 4 * 5 * Copyright (c) 1998 6 * Jordan Hubbard. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer, 13 * verbatim and that no modifications are made prior to this 14 * point in the file. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 33#include <ctype.h> 34#include <stdlib.h> 35#include <string.h> 36#include <libutil.h> 37 38#define MAX_NAME 64 39#define MAX_VALUE 512 40 41static properties 42property_alloc(char *name, char *value) 43{ 44 properties n; 45 46 n = (properties)malloc(sizeof(struct _property)); 47 n->next = NULL; 48 n->name = name ? strdup(name) : NULL; 49 n->value = value ? strdup(value) : NULL; 50 return n; 51} 52 53properties 54properties_read(FILE *fp) 55{ 56 properties head, ptr; 57 char hold_n[MAX_NAME + 1]; 58 char hold_v[MAX_VALUE + 1]; 59 char buf[BUFSIZ * 4]; 60 int bp, n, v, max; 61 enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state; 62 int ch = 0; 63 64 n = v = bp = max = 0; 65 head = ptr = NULL; 66 state = LOOK; 67 while (state != STOP) { 68 if (state != COMMIT) { 69 if (bp == max) 70 state = FILL; 71 else 72 ch = buf[bp++]; 73 } 74 switch(state) { 75 case FILL: 76 if ((max = fread(buf, 1, sizeof buf, fp)) <= 0) { 77 state = STOP; 78 break; 79 } 80 else { 81 state = LOOK; 82 ch = buf[0]; 83 bp = 1; 84 } 85 /* Fall through deliberately since we already have a character and state == LOOK */ 86 87 case LOOK: 88 if (isspace(ch)) 89 continue; 90 /* Allow shell or lisp style comments */ 91 else if (ch == '#' || ch == ';') { 92 state = COMMENT; 93 continue; 94 } 95 else if (isalnum(ch) || ch == '_') { 96 if (n >= MAX_NAME) { 97 n = 0; 98 state = COMMENT; 99 } 100 else { 101 hold_n[n++] = ch; 102 state = NAME; 103 } 104 } 105 else 106 state = COMMENT; /* Ignore the rest of the line */ 107 break; 108 109 case COMMENT: 110 if (ch == '\n') 111 state = LOOK; 112 break; 113 114 case NAME: 115 if (ch == '\n' || !ch) { 116 hold_n[n] = '\0'; 117 hold_v[0] = '\0'; 118 v = n = 0; 119 state = COMMIT; 120 } 121 else if (isspace(ch)) 122 continue; 123 else if (ch == '=') { 124 hold_n[n] = '\0'; 125 v = n = 0; 126 state = VALUE; 127 } 128 else 129 hold_n[n++] = ch; 130 break; 131 132 case VALUE: 133 if (v == 0 && isspace(ch)) 134 continue; 135 else if (ch == '{') 136 state = MVALUE; 137 else if (ch == '\n' || !ch) { 138 hold_v[v] = '\0'; 139 v = n = 0; 140 state = COMMIT; 141 } 142 else { 143 if (v >= MAX_VALUE) { 144 state = COMMENT; 145 v = n = 0; 146 break; 147 } 148 else 149 hold_v[v++] = ch; 150 } 151 break; 152 153 case MVALUE: 154 /* multiline value */ 155 if (v >= MAX_VALUE) { 156 state = COMMENT; 157 n = v = 0; 158 } 159 else if (ch == '}') { 160 hold_v[v] = '\0'; 161 v = n = 0; 162 state = COMMIT; 163 } 164 else 165 hold_v[v++] = ch; 166 break; 167 168 case COMMIT: 169 if (!head) 170 head = ptr = property_alloc(hold_n, hold_v); 171 else { 172 ptr->next = property_alloc(hold_n, hold_v); 173 ptr = ptr->next; 174 } 175 state = LOOK; 176 v = n = 0; 177 break; 178 179 case STOP: 180 /* we don't handle this here, but this prevents warnings */ 181 break; 182 } 183 } 184 return head; 185} 186 187char * 188property_find(properties list, const char *name) 189{ 190 if (!list || !name || !name[0]) 191 return NULL; 192 while (list) { 193 if (!strcmp(list->name, name)) 194 return list->value; 195 list = list->next; 196 } 197 return NULL; 198} 199 200void 201properties_free(properties list) 202{ 203 properties tmp; 204 205 while (list) { 206 tmp = list->next; 207 if (list->name) 208 free(list->name); 209 if (list->value) 210 free(list->value); 211 free(list); 212 list = tmp; 213 } 214} 215 216