Goto sanos source index
//
// inifile.c
//
// Property files
//
// Copyright (C) 2002 Michael Ringgaard. 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.
// 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.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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, 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 <os.h>
#include <string.h>
#include <stdlib.h>
#include <inifile.h>
#ifdef KERNEL
#include <os/krnl.h>
#endif
static char *trimstr(char *s, char *end)
{
char *str;
char *t;
int ch;
int i;
while (end > s)
{
if (*(end - 1) == ' ' || *(end - 1) == '\t')
end--;
else
break;
}
if (end == s) return NULL;
t = str = (char *) malloc(end - s + 1);
while (s < end)
{
if (*s == '^')
{
s++;
ch = 0;
for (i = 0; i < 2; i++)
{
if (s == end) break;
if (*s >= '0' && *s <= '9')
ch = (ch << 4) + *s - '0';
else if (*s >= 'A' && *s <= 'F')
ch = (ch << 4) + *s + 10 - 'A';
else if (*s >= 'a' && *s <= 'f')
ch = (ch << 4) + *s + 10 - 'a';
else
break;
s++;
}
*t++ = ch;
}
else
*t++ = *s++;
}
*t = 0;
return str;
}
struct section *find_section(struct section *sect, char *name)
{
while (sect)
{
if (strcmp(sect->name, name) == 0) return sect;
sect = sect->next;
}
return NULL;
}
int get_section_size(struct section *sect)
{
struct property *prop;
int n;
if (!sect) return 0;
prop = sect->properties;
n = 0;
while (prop)
{
n++;
prop = prop->next;
}
return n;
}
char *find_property(struct section *sect, char *name)
{
struct property *prop;
if (!sect) return NULL;
prop = sect->properties;
while (prop)
{
if (strcmp(prop->name, name) == 0) return prop->value ? prop->value : "";
prop = prop->next;
}
return NULL;
}
char *get_property(struct section *sections, char *sectname, char *propname, char *defval)
{
struct section *sect;
char *val;
sect = find_section(sections, sectname);
if (!sect) return defval;
val = find_property(sect, propname);
return val ? val : defval;
}
int get_numeric_property(struct section *sections, char *sectname, char *propname, int defval)
{
char *val;
val = get_property(sections, sectname, propname, NULL);
return val ? atoi(val) : defval;
}
void free_properties(struct section *sect)
{
struct section *nextsect;
struct property *prop;
struct property *nextprop;
while (sect)
{
if (sect->name) free(sect->name);
prop = sect->properties;
while (prop)
{
if (prop->name) free(prop->name);
if (prop->value) free(prop->value);
nextprop = prop->next;
free(prop);
prop = nextprop;
}
nextsect = sect->next;
free(sect);
sect = nextsect;
}
}
struct section *parse_properties(char *props)
{
struct section *secthead = NULL;
struct section *sect = NULL;
struct property *prop = NULL;
char *p;
char *end;
char *split;
p = props;
while (*p)
{
// Skip white at start of line
while (*p == ' ' || *p == '\t') p++;
// Skip comments
if (*p == '#' || *p == ';')
{
while (*p && *p != '\r' && *p != '\n') p++;
if (*p == '\r') p++;
if (*p == '\n') p++;
continue;
}
// Skip blank lines
if (*p == 0 || *p == '\r' || *p == '\n')
{
if (*p == '\r') p++;
if (*p == '\n') p++;
continue;
}
// Check for section or property
if (*p == '[')
{
struct section *newsect;
p++;
end = p;
while (*end && *end != ']') end++;
newsect = (struct section *) malloc(sizeof(struct section));
if (!newsect) return NULL;
newsect->name = trimstr(p, end);
newsect->next = NULL;
newsect->properties = NULL;
if (!secthead) secthead = newsect;
if (sect) sect->next = newsect;
sect = newsect;
prop = NULL;
p = end;
if (*p == ']') p++;
}
else
{
struct property *newprop;
end = p;
split = NULL;
while (*end && *end != '\r' && *end != '\n')
{
if (!split && (*end == '=' || *end == ':')) split = end;
end++;
}
if (sect)
{
newprop = (struct property *) malloc(sizeof(struct property));
if (!newprop) return NULL;
if (split)
{
newprop->name = trimstr(p, split);
split++;
while (*split == ' ' || *split == '\t') split++;
newprop->value = trimstr(split, end);
}
else
{
newprop->name = trimstr(p, end);
newprop->value = NULL;
}
newprop->next = NULL;
if (prop)
prop->next = newprop;
else
sect->properties = newprop;
prop = newprop;
}
p = end;
if (*p == '\r') p++;
if (*p == '\n') p++;
}
}
return secthead;
}
#ifndef KERNEL
void list_properties(int f, struct section *sect)
{
struct property *prop;
while (sect)
{
write(f, "[", 1);
write(f, sect->name, strlen(sect->name));
write(f, "]\r\n", 3);
prop = sect->properties;
while (prop)
{
write(f, prop->name, strlen(prop->name));
if (prop->value)
{
write(f, "=", 1);
write(f, prop->value, strlen(prop->value));
}
write(f, "\r\n", 2);
prop = prop->next;
}
if (sect->next) write(f, "\r\n", 2);
sect = sect->next;
}
}
struct section *read_properties(char *filename)
{
int f;
int size;
struct stat64 buffer;
char *props;
struct section *sect;
f = open(filename, O_BINARY);
if (f < 0) return NULL;
fstat64(f, &buffer);
size = (int) buffer.st_size;
props = (char *) malloc(size + 1);
if (!props)
{
close(f);
return NULL;
}
if (read(f, props, size) != size)
{
free(props);
close(f);
return NULL;
}
close(f);
props[size] = 0;
sect = parse_properties(props);
free(props);
return sect;
}
#endif