summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/myndbm.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
committerpeter <peter@FreeBSD.org>1996-08-20 23:46:10 +0000
commit8982e501c77217c860f79bba431f46a62b607a21 (patch)
tree70187fdf5be4cbefd0baf46bddac7e5e32c13c24 /contrib/cvs/src/myndbm.c
parent01ee40fd6a76f6ff7ef247fc1b2cf6e337f216c5 (diff)
downloadFreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.zip
FreeBSD-src-8982e501c77217c860f79bba431f46a62b607a21.tar.gz
Import of slightly trimmed cvs-1.8 distribution. Generated files
and non-unix code has been left out.
Diffstat (limited to 'contrib/cvs/src/myndbm.c')
-rw-r--r--contrib/cvs/src/myndbm.c288
1 files changed, 288 insertions, 0 deletions
diff --git a/contrib/cvs/src/myndbm.c b/contrib/cvs/src/myndbm.c
new file mode 100644
index 0000000..527f7ee
--- /dev/null
+++ b/contrib/cvs/src/myndbm.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 1992, Brian Berliner
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS 1.4 kit.
+ *
+ * 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 <assert.h>
+#include "cvs.h"
+#include "getline.h"
+
+#ifdef MY_NDBM
+
+static void mydbm_load_file ();
+
+/* ARGSUSED */
+DBM *
+mydbm_open (file, flags, mode)
+ char *file;
+ int flags;
+ int mode;
+{
+ FILE *fp;
+ DBM *db;
+
+ fp = fopen (file, FOPEN_BINARY_READ);
+ if (fp == NULL && !(existence_error (errno) && (flags & O_CREAT)))
+ return ((DBM *) 0);
+
+ db = (DBM *) xmalloc (sizeof (*db));
+ db->dbm_list = getlist ();
+ db->modified = 0;
+ db->name = xstrdup (file);
+
+ if (fp != NULL)
+ {
+ mydbm_load_file (fp, db->dbm_list);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", file);
+ }
+ return (db);
+}
+
+static int write_item PROTO ((Node *, void *));
+
+static int
+write_item (node, data)
+ Node *node;
+ void *data;
+{
+ FILE *fp = (FILE *)data;
+ fputs (node->key, fp);
+ fputs (" ", fp);
+ fputs (node->data, fp);
+ fputs ("\012", fp);
+ return 0;
+}
+
+void
+mydbm_close (db)
+ DBM *db;
+{
+ if (db->modified)
+ {
+ FILE *fp;
+ fp = fopen (db->name, FOPEN_BINARY_WRITE);
+ if (fp == NULL)
+ error (1, errno, "cannot write %s", db->name);
+ walklist (db->dbm_list, write_item, (void *)fp);
+ if (fclose (fp) < 0)
+ error (0, errno, "cannot close %s", db->name);
+ }
+ free (db->name);
+ 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);
+}
+
+/* Note: only updates the in-memory copy, which is written out at
+ mydbm_close time. Note: Also differs from DBM in that on duplication,
+ it gives a warning, rather than either DBM_INSERT or DBM_REPLACE
+ behavior. */
+int
+mydbm_store (db, key, value, flags)
+ DBM *db;
+ datum key;
+ datum value;
+ int flags;
+{
+ Node *node;
+
+ node = getnode ();
+ node->type = NDBMNODE;
+
+ node->key = xmalloc (key.dsize + 1);
+ strncpy (node->key, key.dptr, key.dsize);
+ node->key[key.dsize] = '\0';
+
+ node->data = xmalloc (value.dsize + 1);
+ strncpy (node->data, value.dptr, value.dsize);
+ node->data[value.dsize] = '\0';
+
+ db->modified = 1;
+ if (addnode (db->dbm_list, node) == -1)
+ {
+ error (0, 0, "attempt to insert duplicate key `%s'", node->key);
+ freenode (node);
+ return 0;
+ }
+ return 0;
+}
+
+static void
+mydbm_load_file (fp, list)
+ FILE *fp;
+ List *list;
+{
+ char *line = NULL;
+ size_t line_len;
+ /* FIXME: arbitrary limit. */
+ char value[MAXLINELEN];
+ char *cp, *vp;
+ int len, cont;
+
+ for (cont = 0; getline (&line, &line_len, fp) >= 0;)
+ {
+ if ((cp = strrchr (line, '\012')) != NULL)
+ *cp = '\0'; /* strip the newline */
+ cp = line + strlen (line);
+ if (cp > line && cp[-1] == '\015')
+ /* If the file (e.g. modules) was written on an NT box, it will
+ contain CRLF at the ends of lines. Strip them (we can't do
+ this by opening the file in text mode because we might be
+ running on unix). */
+ cp[-1] = '\0';
+
+ /*
+ * 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);
+ }
+ }
+ }
+ free (line);
+}
+
+#endif /* MY_NDBM */
OpenPOWER on IntegriCloud