mirror of
https://github.com/ctm/executor.git
synced 2024-06-16 04:29:29 +00:00
309 lines
5.4 KiB
C
309 lines
5.4 KiB
C
|
/*
|
||
|
* Copyright 1997 by Abacus Research and
|
||
|
* Development, Inc. All rights reserved.
|
||
|
*/
|
||
|
|
||
|
#if !defined (OMIT_RCSID_STRINGS)
|
||
|
char ROMlib_rcsid_ini[] =
|
||
|
"$Id: ini.c 88 2005-05-25 03:59:37Z ctm $";
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Yahoo -- yet another configuration file thingy. Who needs YACC when
|
||
|
* you expect your end user to be familiar with DOS .ini files?
|
||
|
*/
|
||
|
|
||
|
#include "rsys/common.h"
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "rsys/ini.h"
|
||
|
|
||
|
typedef struct heading_link_str
|
||
|
{
|
||
|
struct heading_link_str *next;
|
||
|
heading_t heading;
|
||
|
pair_link_t *pairs;
|
||
|
}
|
||
|
heading_link_t;
|
||
|
|
||
|
PRIVATE heading_link_t *headings;
|
||
|
|
||
|
PUBLIC heading_t
|
||
|
new_heading (unsigned char *start, int len)
|
||
|
{
|
||
|
heading_t retval;
|
||
|
heading_link_t *linkp;
|
||
|
|
||
|
linkp = malloc (sizeof *linkp);
|
||
|
if (!linkp)
|
||
|
retval = NULL;
|
||
|
else
|
||
|
{
|
||
|
linkp->heading = malloc (len + 1);
|
||
|
if (!linkp->heading)
|
||
|
{
|
||
|
retval = NULL;
|
||
|
free (linkp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
strncpy (linkp->heading, (char *) start, len);
|
||
|
linkp->heading[len] = 0;
|
||
|
linkp->next = headings;
|
||
|
linkp->pairs = 0;
|
||
|
headings = linkp;
|
||
|
retval = linkp->heading;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PRIVATE heading_link_t *
|
||
|
find_heading (heading_t heading)
|
||
|
{
|
||
|
static heading_link_t *cachep;
|
||
|
heading_link_t *retval;
|
||
|
|
||
|
if (cachep && strcmp (cachep->heading, heading) == 0)
|
||
|
retval = cachep;
|
||
|
else
|
||
|
{
|
||
|
for (retval = headings;
|
||
|
retval && strcmp (retval->heading, heading) != 0;
|
||
|
retval = retval->next)
|
||
|
;
|
||
|
if (retval)
|
||
|
cachep = retval;
|
||
|
}
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC void
|
||
|
new_key_value_pair (heading_t heading, unsigned char *keystart, int keylen,
|
||
|
unsigned char *valuestart, int valuelen)
|
||
|
{
|
||
|
pair_link_t *pairp;
|
||
|
|
||
|
pairp = malloc (sizeof *pairp);
|
||
|
if (pairp)
|
||
|
{
|
||
|
pairp->key = malloc (keylen+1);
|
||
|
if (!pairp->key)
|
||
|
free (pairp);
|
||
|
else
|
||
|
{
|
||
|
pairp->value = malloc (valuelen+1);
|
||
|
if (!pairp->value)
|
||
|
{
|
||
|
free (pairp->key);
|
||
|
free (pairp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
heading_link_t *headingp;
|
||
|
|
||
|
strncpy (pairp->key, (char *) keystart, keylen);
|
||
|
pairp->key[keylen] = 0;
|
||
|
strncpy (pairp->value, (char *) valuestart, valuelen);
|
||
|
pairp->value[valuelen] = 0;
|
||
|
headingp = find_heading (heading);
|
||
|
pairp->next = 0;
|
||
|
if (!headingp)
|
||
|
{
|
||
|
warning_unexpected ("couldn't find %s", heading);
|
||
|
free (pairp->key);
|
||
|
free (pairp->value);
|
||
|
free (pairp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pair_link_t **pairpp;
|
||
|
|
||
|
for (pairpp = &headingp->pairs;
|
||
|
*pairpp;
|
||
|
pairpp = &(*pairpp)->next)
|
||
|
;
|
||
|
*pairpp = pairp;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
/* This routine is currently unsafe to use because it might result in
|
||
|
dangling pointers */
|
||
|
PUBLIC void
|
||
|
discard_all_inis (void)
|
||
|
{
|
||
|
heading_link_t *headerp, *nextheaderp;
|
||
|
|
||
|
for (headerp = headings; headerp; headerp = nextheaderp)
|
||
|
{
|
||
|
nextheaderp = headerp->next;
|
||
|
{
|
||
|
pair_link_t *pairp, *nextpairp;
|
||
|
|
||
|
for (pairp = headerp->pairs; pairp; pairp = nextpairp)
|
||
|
{
|
||
|
nextpairp = pairp->next;
|
||
|
free (pairp->key);
|
||
|
free (pairp->value);
|
||
|
free (pairp);
|
||
|
}
|
||
|
}
|
||
|
free (headerp);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
PUBLIC boolean_t
|
||
|
read_ini_file (const char *filename)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
boolean_t retval;
|
||
|
|
||
|
fp = fopen (filename, "r");
|
||
|
if (fp)
|
||
|
{
|
||
|
heading_t heading;
|
||
|
int line;
|
||
|
|
||
|
heading = "";
|
||
|
line = 0;
|
||
|
while (!feof (fp))
|
||
|
{
|
||
|
unsigned char buf[1024];
|
||
|
unsigned char *p;
|
||
|
|
||
|
++line;
|
||
|
if (!fgets ((char *) buf, sizeof buf, fp))
|
||
|
buf[0] = 0;
|
||
|
|
||
|
for (p = buf; *p && isspace (*p); ++p)
|
||
|
;
|
||
|
switch (*p)
|
||
|
{
|
||
|
case '[':
|
||
|
{
|
||
|
unsigned char *ep;
|
||
|
|
||
|
++p;
|
||
|
ep = (unsigned char *) strrchr ((char *) p, ']');
|
||
|
if (*ep)
|
||
|
heading = new_heading (p, ep - p);
|
||
|
else
|
||
|
warning_unexpected ("missing ] on line %d", line);
|
||
|
}
|
||
|
break;
|
||
|
case '#':
|
||
|
case 0:
|
||
|
break;
|
||
|
default:
|
||
|
{
|
||
|
unsigned char *eq;
|
||
|
|
||
|
eq = (unsigned char *) strchr ((char *) p, '=');
|
||
|
if (!eq)
|
||
|
warning_unexpected ("missing = on line %d", line);
|
||
|
else
|
||
|
{
|
||
|
unsigned char *ep;
|
||
|
|
||
|
ep = p + strlen ((char *) p);
|
||
|
while (isspace (*(ep-1)))
|
||
|
--ep;
|
||
|
new_key_value_pair (heading, p, eq - p, eq+1, ep-eq-1);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
retval = !!fp;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC pair_link_t *
|
||
|
get_pair_link_n (heading_t heading, int n)
|
||
|
{
|
||
|
pair_link_t *retval;
|
||
|
heading_link_t *headingp;
|
||
|
|
||
|
retval = NULL;
|
||
|
headingp = find_heading (heading);
|
||
|
if (headingp)
|
||
|
{
|
||
|
retval = headingp->pairs;
|
||
|
while (retval && n > 0)
|
||
|
{
|
||
|
retval = retval->next;
|
||
|
--n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC FILE *
|
||
|
open_ini_file_for_writing (const char *filename)
|
||
|
{
|
||
|
FILE *retval;
|
||
|
|
||
|
retval = fopen (filename, "w");
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC boolean_t
|
||
|
add_heading_to_file (FILE *fp, heading_t heading)
|
||
|
{
|
||
|
boolean_t retval;
|
||
|
|
||
|
retval = fprintf (fp, "[%s]\n", heading) > 0;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC boolean_t
|
||
|
add_key_value_to_file (FILE *fp, ini_key_t key, value_t value)
|
||
|
{
|
||
|
boolean_t retval;
|
||
|
|
||
|
retval = fprintf (fp, "%s=%s\n", key, value) > 0;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC boolean_t
|
||
|
close_ini_file (FILE *fp)
|
||
|
{
|
||
|
boolean_t retval;
|
||
|
|
||
|
retval = fclose (fp) == 0;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PUBLIC value_t
|
||
|
find_key (heading_t heading, ini_key_t key)
|
||
|
{
|
||
|
value_t retval;
|
||
|
heading_link_t *headingp;
|
||
|
|
||
|
retval = NULL;
|
||
|
if (heading && key)
|
||
|
{
|
||
|
headingp = find_heading (heading);
|
||
|
if (headingp)
|
||
|
{
|
||
|
pair_link_t *pairp;
|
||
|
|
||
|
for (pairp = headingp->pairs;
|
||
|
pairp && strcmp (pairp->key, key) != 0;
|
||
|
pairp = pairp->next)
|
||
|
;
|
||
|
if (pairp)
|
||
|
retval = pairp->value;
|
||
|
}
|
||
|
}
|
||
|
return retval;
|
||
|
}
|