property.c revision 40040
140040Sjkh/* 240040Sjkh * 340040Sjkh * Simple property list handling code. 440040Sjkh * 540040Sjkh * Copyright (c) 1998 640040Sjkh * Jordan Hubbard. All rights reserved. 740040Sjkh * 840040Sjkh * Redistribution and use in source and binary forms, with or without 940040Sjkh * modification, are permitted provided that the following conditions 1040040Sjkh * are met: 1140040Sjkh * 1. Redistributions of source code must retain the above copyright 1240040Sjkh * notice, this list of conditions and the following disclaimer, 1340040Sjkh * verbatim and that no modifications are made prior to this 1440040Sjkh * point in the file. 1540040Sjkh * 2. Redistributions in binary form must reproduce the above copyright 1640040Sjkh * notice, this list of conditions and the following disclaimer in the 1740040Sjkh * documentation and/or other materials provided with the distribution. 1840040Sjkh * 1940040Sjkh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2040040Sjkh * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2140040Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2240040Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR HIS PETS BE LIABLE 2340040Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2440040Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2540040Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 2640040Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2740040Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2840040Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2940040Sjkh * SUCH DAMAGE. 3040040Sjkh * 3140040Sjkh */ 3240040Sjkh 3340040Sjkh#include <ctype.h> 3440040Sjkh#include <stdlib.h> 3540040Sjkh#include <string.h> 3640040Sjkh#include <libutil.h> 3740040Sjkh 3840040Sjkh#define MAX_NAME 64 3940040Sjkh#define MAX_VALUE 512 4040040Sjkh 4140040Sjkhstatic properties 4240040Sjkhproperty_alloc(char *name, char *value) 4340040Sjkh{ 4440040Sjkh properties n; 4540040Sjkh 4640040Sjkh n = (properties)malloc(sizeof(struct _property)); 4740040Sjkh n->next = NULL; 4840040Sjkh n->name = name ? strdup(name) : NULL; 4940040Sjkh n->value = value ? strdup(value) : NULL; 5040040Sjkh return n; 5140040Sjkh} 5240040Sjkh 5340040Sjkhproperties 5440040Sjkhproperties_read(FILE *fp) 5540040Sjkh{ 5640040Sjkh properties head, ptr; 5740040Sjkh char hold_n[MAX_NAME + 1]; 5840040Sjkh char hold_v[MAX_VALUE + 1]; 5940040Sjkh char buf[BUFSIZ * 4]; 6040040Sjkh int bp, n, v, max; 6140040Sjkh enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state; 6240040Sjkh int ch = 0; 6340040Sjkh 6440040Sjkh n = v = bp = max = 0; 6540040Sjkh head = ptr = NULL; 6640040Sjkh state = LOOK; 6740040Sjkh while (state != STOP) { 6840040Sjkh if (state != COMMIT) { 6940040Sjkh if (bp == max) 7040040Sjkh state = FILL; 7140040Sjkh else 7240040Sjkh ch = buf[bp++]; 7340040Sjkh } 7440040Sjkh switch(state) { 7540040Sjkh case FILL: 7640040Sjkh if ((max = fread(buf, 1, sizeof buf, fp)) <= 0) { 7740040Sjkh state = STOP; 7840040Sjkh break; 7940040Sjkh } 8040040Sjkh else { 8140040Sjkh state = LOOK; 8240040Sjkh ch = buf[0]; 8340040Sjkh bp = 1; 8440040Sjkh } 8540040Sjkh /* Fall through deliberately since we already have a character and state == LOOK */ 8640040Sjkh 8740040Sjkh case LOOK: 8840040Sjkh if (isspace(ch)) 8940040Sjkh continue; 9040040Sjkh /* Allow shell or lisp style comments */ 9140040Sjkh else if (ch == '#' || ch == ';') { 9240040Sjkh state = COMMENT; 9340040Sjkh continue; 9440040Sjkh } 9540040Sjkh else if (isalnum(ch) || ch == '_') { 9640040Sjkh if (n >= MAX_NAME) { 9740040Sjkh n = 0; 9840040Sjkh state = COMMENT; 9940040Sjkh } 10040040Sjkh else { 10140040Sjkh hold_n[n++] = ch; 10240040Sjkh state = NAME; 10340040Sjkh } 10440040Sjkh } 10540040Sjkh else 10640040Sjkh state = COMMENT; /* Ignore the rest of the line */ 10740040Sjkh break; 10840040Sjkh 10940040Sjkh case COMMENT: 11040040Sjkh if (ch == '\n') 11140040Sjkh state = LOOK; 11240040Sjkh break; 11340040Sjkh 11440040Sjkh case NAME: 11540040Sjkh if (ch == '\n' || !ch) { 11640040Sjkh hold_n[n] = '\0'; 11740040Sjkh hold_v[0] = '\0'; 11840040Sjkh v = n = 0; 11940040Sjkh state = COMMIT; 12040040Sjkh } 12140040Sjkh else if (isspace(ch)) 12240040Sjkh continue; 12340040Sjkh else if (ch == '=') { 12440040Sjkh hold_n[n] = '\0'; 12540040Sjkh v = n = 0; 12640040Sjkh state = VALUE; 12740040Sjkh } 12840040Sjkh else 12940040Sjkh hold_n[n++] = ch; 13040040Sjkh break; 13140040Sjkh 13240040Sjkh case VALUE: 13340040Sjkh if (v == 0 && isspace(ch)) 13440040Sjkh continue; 13540040Sjkh else if (ch == '{') 13640040Sjkh state = MVALUE; 13740040Sjkh else if (ch == '\n' || !ch) { 13840040Sjkh hold_v[v] = '\0'; 13940040Sjkh v = n = 0; 14040040Sjkh state = COMMIT; 14140040Sjkh } 14240040Sjkh else { 14340040Sjkh if (v >= MAX_VALUE) { 14440040Sjkh state = COMMENT; 14540040Sjkh v = n = 0; 14640040Sjkh break; 14740040Sjkh } 14840040Sjkh else 14940040Sjkh hold_v[v++] = ch; 15040040Sjkh } 15140040Sjkh break; 15240040Sjkh 15340040Sjkh case MVALUE: 15440040Sjkh /* multiline value */ 15540040Sjkh if (v >= MAX_VALUE) { 15640040Sjkh state = COMMENT; 15740040Sjkh n = v = 0; 15840040Sjkh } 15940040Sjkh else if (ch == '}') { 16040040Sjkh hold_v[v] = '\0'; 16140040Sjkh v = n = 0; 16240040Sjkh state = COMMIT; 16340040Sjkh } 16440040Sjkh else 16540040Sjkh hold_v[v++] = ch; 16640040Sjkh break; 16740040Sjkh 16840040Sjkh case COMMIT: 16940040Sjkh if (!head) 17040040Sjkh head = ptr = property_alloc(hold_n, hold_v); 17140040Sjkh else { 17240040Sjkh ptr->next = property_alloc(hold_n, hold_v); 17340040Sjkh ptr = ptr->next; 17440040Sjkh } 17540040Sjkh state = LOOK; 17640040Sjkh v = n = 0; 17740040Sjkh break; 17840040Sjkh 17940040Sjkh case STOP: 18040040Sjkh /* we don't handle this here, but this prevents warnings */ 18140040Sjkh break; 18240040Sjkh } 18340040Sjkh } 18440040Sjkh return head; 18540040Sjkh} 18640040Sjkh 18740040Sjkhchar * 18840040Sjkhproperty_find(properties list, const char *name) 18940040Sjkh{ 19040040Sjkh if (!list || !name || !name[0]) 19140040Sjkh return NULL; 19240040Sjkh while (list) { 19340040Sjkh if (!strcmp(list->name, name)) 19440040Sjkh return list->value; 19540040Sjkh list = list->next; 19640040Sjkh } 19740040Sjkh return NULL; 19840040Sjkh} 19940040Sjkh 20040040Sjkhvoid 20140040Sjkhproperties_free(properties list) 20240040Sjkh{ 20340040Sjkh properties tmp; 20440040Sjkh 20540040Sjkh while (list) { 20640040Sjkh tmp = list->next; 20740040Sjkh if (list->name) 20840040Sjkh free(list->name); 20940040Sjkh if (list->value) 21040040Sjkh free(list->value); 21140040Sjkh free(list); 21240040Sjkh list = tmp; 21340040Sjkh } 21440040Sjkh} 21540040Sjkh 216