1993-06-18 07:46:17 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 1992, Brian Berliner
|
|
|
|
*
|
|
|
|
* You may distribute under the terms of the GNU General Public License as
|
1995-03-31 09:45:33 +02:00
|
|
|
* specified in the README file that comes with the CVS 1.4 kit.
|
1993-06-18 07:46:17 +02:00
|
|
|
*
|
|
|
|
* A simple ndbm-emulator for CVS. It parses a text file of the format:
|
|
|
|
*
|
|
|
|
* key value
|
|
|
|
*
|
|
|
|
* at dbm_open time, and loads the entire file into memory. As such, it is
|
|
|
|
* probably only good for fairly small modules files. Ours is about 30K in
|
|
|
|
* size, and this code works fine.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "cvs.h"
|
|
|
|
|
|
|
|
#ifdef MY_NDBM
|
|
|
|
|
|
|
|
#ifndef lint
|
1995-12-10 23:31:58 +01:00
|
|
|
static const char rcsid[] = "$CVSid: @(#)myndbm.c 1.7 94/09/23 $";
|
|
|
|
USE(rcsid);
|
1993-06-18 07:46:17 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
static void mydbm_load_file ();
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
DBM *
|
|
|
|
mydbm_open (file, flags, mode)
|
|
|
|
char *file;
|
|
|
|
int flags;
|
|
|
|
int mode;
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
DBM *db;
|
|
|
|
|
|
|
|
if ((fp = fopen (file, "r")) == NULL)
|
|
|
|
return ((DBM *) 0);
|
|
|
|
|
|
|
|
db = (DBM *) xmalloc (sizeof (*db));
|
|
|
|
db->dbm_list = getlist ();
|
|
|
|
|
|
|
|
mydbm_load_file (fp, db->dbm_list);
|
|
|
|
(void) fclose (fp);
|
|
|
|
return (db);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mydbm_close (db)
|
|
|
|
DBM *db;
|
|
|
|
{
|
|
|
|
dellist (&db->dbm_list);
|
|
|
|
free ((char *) db);
|
|
|
|
}
|
|
|
|
|
|
|
|
datum
|
|
|
|
mydbm_fetch (db, key)
|
|
|
|
DBM *db;
|
|
|
|
datum key;
|
|
|
|
{
|
|
|
|
Node *p;
|
|
|
|
char *s;
|
|
|
|
datum val;
|
|
|
|
|
|
|
|
/* make sure it's null-terminated */
|
|
|
|
s = xmalloc (key.dsize + 1);
|
|
|
|
(void) strncpy (s, key.dptr, key.dsize);
|
|
|
|
s[key.dsize] = '\0';
|
|
|
|
|
|
|
|
p = findnode (db->dbm_list, s);
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
val.dptr = p->data;
|
|
|
|
val.dsize = strlen (p->data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
val.dptr = (char *) NULL;
|
|
|
|
val.dsize = 0;
|
|
|
|
}
|
|
|
|
free (s);
|
|
|
|
return (val);
|
|
|
|
}
|
|
|
|
|
|
|
|
datum
|
|
|
|
mydbm_firstkey (db)
|
|
|
|
DBM *db;
|
|
|
|
{
|
|
|
|
Node *head, *p;
|
|
|
|
datum key;
|
|
|
|
|
|
|
|
head = db->dbm_list->list;
|
|
|
|
p = head->next;
|
|
|
|
if (p != head)
|
|
|
|
{
|
|
|
|
key.dptr = p->key;
|
|
|
|
key.dsize = strlen (p->key);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
key.dptr = (char *) NULL;
|
|
|
|
key.dsize = 0;
|
|
|
|
}
|
|
|
|
db->dbm_next = p->next;
|
|
|
|
return (key);
|
|
|
|
}
|
|
|
|
|
|
|
|
datum
|
|
|
|
mydbm_nextkey (db)
|
|
|
|
DBM *db;
|
|
|
|
{
|
|
|
|
Node *head, *p;
|
|
|
|
datum key;
|
|
|
|
|
|
|
|
head = db->dbm_list->list;
|
|
|
|
p = db->dbm_next;
|
|
|
|
if (p != head)
|
|
|
|
{
|
|
|
|
key.dptr = p->key;
|
|
|
|
key.dsize = strlen (p->key);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
key.dptr = (char *) NULL;
|
|
|
|
key.dsize = 0;
|
|
|
|
}
|
|
|
|
db->dbm_next = p->next;
|
|
|
|
return (key);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
mydbm_load_file (fp, list)
|
|
|
|
FILE *fp;
|
|
|
|
List *list;
|
|
|
|
{
|
|
|
|
char line[MAXLINELEN], value[MAXLINELEN];
|
|
|
|
char *cp, *vp;
|
|
|
|
int len, cont;
|
|
|
|
|
|
|
|
for (cont = 0; fgets (line, sizeof (line), fp) != NULL;)
|
|
|
|
{
|
1995-03-31 09:45:33 +02:00
|
|
|
if ((cp = strrchr (line, '\n')) != NULL)
|
1993-06-18 07:46:17 +02:00
|
|
|
*cp = '\0'; /* strip the newline */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add the line to the value, at the end if this is a continuation
|
|
|
|
* line; otherwise at the beginning, but only after any trailing
|
|
|
|
* backslash is removed.
|
|
|
|
*/
|
|
|
|
vp = value;
|
|
|
|
if (cont)
|
|
|
|
vp += strlen (value);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* See if the line we read is a continuation line, and strip the
|
|
|
|
* backslash if so.
|
|
|
|
*/
|
|
|
|
len = strlen (line);
|
|
|
|
if (len > 0)
|
|
|
|
cp = &line[len - 1];
|
|
|
|
else
|
|
|
|
cp = line;
|
|
|
|
if (*cp == '\\')
|
|
|
|
{
|
|
|
|
cont = 1;
|
|
|
|
*cp = '\0';
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cont = 0;
|
|
|
|
}
|
|
|
|
(void) strcpy (vp, line);
|
|
|
|
if (value[0] == '#')
|
|
|
|
continue; /* comment line */
|
|
|
|
vp = value;
|
|
|
|
while (*vp && isspace (*vp))
|
|
|
|
vp++;
|
|
|
|
if (*vp == '\0')
|
|
|
|
continue; /* empty line */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this was not a continuation line, add the entry to the database
|
|
|
|
*/
|
|
|
|
if (!cont)
|
|
|
|
{
|
|
|
|
Node *p = getnode ();
|
|
|
|
char *kp;
|
|
|
|
|
|
|
|
kp = vp;
|
|
|
|
while (*vp && !isspace (*vp))
|
|
|
|
vp++;
|
|
|
|
*vp++ = '\0'; /* NULL terminate the key */
|
|
|
|
p->type = NDBMNODE;
|
|
|
|
p->key = xstrdup (kp);
|
|
|
|
while (*vp && isspace (*vp))
|
|
|
|
vp++; /* skip whitespace to value */
|
|
|
|
if (*vp == '\0')
|
|
|
|
{
|
|
|
|
error (0, 0, "warning: NULL value for key `%s'", p->key);
|
|
|
|
freenode (p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p->data = xstrdup (vp);
|
|
|
|
if (addnode (list, p) == -1)
|
|
|
|
{
|
|
|
|
error (0, 0, "duplicate key found for `%s'", p->key);
|
|
|
|
freenode (p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* MY_NDBM */
|