Commit | Line | Data |
---|---|---|
fe37a9c9 WJ |
1 | /* |
2 | * Copyright (c) 1992, Brian Berliner | |
3 | * | |
4 | * You may distribute under the terms of the GNU General Public License as | |
5 | * specified in the README file that comes with the CVS 1.3 kit. | |
6 | * | |
7 | * A simple ndbm-emulator for CVS. It parses a text file of the format: | |
8 | * | |
9 | * key value | |
10 | * | |
11 | * at dbm_open time, and loads the entire file into memory. As such, it is | |
12 | * probably only good for fairly small modules files. Ours is about 30K in | |
13 | * size, and this code works fine. | |
14 | */ | |
15 | ||
16 | #include "cvs.h" | |
17 | ||
18 | #ifdef MY_NDBM | |
19 | ||
20 | #ifndef lint | |
21 | static char rcsid[] = "@(#)myndbm.c 1.5 92/03/31"; | |
22 | #endif | |
23 | ||
24 | static void mydbm_load_file (); | |
25 | ||
26 | /* ARGSUSED */ | |
27 | DBM * | |
28 | mydbm_open (file, flags, mode) | |
29 | char *file; | |
30 | int flags; | |
31 | int mode; | |
32 | { | |
33 | FILE *fp; | |
34 | DBM *db; | |
35 | ||
36 | if ((fp = fopen (file, "r")) == NULL) | |
37 | return ((DBM *) 0); | |
38 | ||
39 | db = (DBM *) xmalloc (sizeof (*db)); | |
40 | db->dbm_list = getlist (); | |
41 | ||
42 | mydbm_load_file (fp, db->dbm_list); | |
43 | (void) fclose (fp); | |
44 | return (db); | |
45 | } | |
46 | ||
47 | void | |
48 | mydbm_close (db) | |
49 | DBM *db; | |
50 | { | |
51 | dellist (&db->dbm_list); | |
52 | free ((char *) db); | |
53 | } | |
54 | ||
55 | datum | |
56 | mydbm_fetch (db, key) | |
57 | DBM *db; | |
58 | datum key; | |
59 | { | |
60 | Node *p; | |
61 | char *s; | |
62 | datum val; | |
63 | ||
64 | /* make sure it's null-terminated */ | |
65 | s = xmalloc (key.dsize + 1); | |
66 | (void) strncpy (s, key.dptr, key.dsize); | |
67 | s[key.dsize] = '\0'; | |
68 | ||
69 | p = findnode (db->dbm_list, s); | |
70 | if (p) | |
71 | { | |
72 | val.dptr = p->data; | |
73 | val.dsize = strlen (p->data); | |
74 | } | |
75 | else | |
76 | { | |
77 | val.dptr = (char *) NULL; | |
78 | val.dsize = 0; | |
79 | } | |
80 | free (s); | |
81 | return (val); | |
82 | } | |
83 | ||
84 | datum | |
85 | mydbm_firstkey (db) | |
86 | DBM *db; | |
87 | { | |
88 | Node *head, *p; | |
89 | datum key; | |
90 | ||
91 | head = db->dbm_list->list; | |
92 | p = head->next; | |
93 | if (p != head) | |
94 | { | |
95 | key.dptr = p->key; | |
96 | key.dsize = strlen (p->key); | |
97 | } | |
98 | else | |
99 | { | |
100 | key.dptr = (char *) NULL; | |
101 | key.dsize = 0; | |
102 | } | |
103 | db->dbm_next = p->next; | |
104 | return (key); | |
105 | } | |
106 | ||
107 | datum | |
108 | mydbm_nextkey (db) | |
109 | DBM *db; | |
110 | { | |
111 | Node *head, *p; | |
112 | datum key; | |
113 | ||
114 | head = db->dbm_list->list; | |
115 | p = db->dbm_next; | |
116 | if (p != head) | |
117 | { | |
118 | key.dptr = p->key; | |
119 | key.dsize = strlen (p->key); | |
120 | } | |
121 | else | |
122 | { | |
123 | key.dptr = (char *) NULL; | |
124 | key.dsize = 0; | |
125 | } | |
126 | db->dbm_next = p->next; | |
127 | return (key); | |
128 | } | |
129 | ||
130 | static void | |
131 | mydbm_load_file (fp, list) | |
132 | FILE *fp; | |
133 | List *list; | |
134 | { | |
135 | char line[MAXLINELEN], value[MAXLINELEN]; | |
136 | char *cp, *vp; | |
137 | int len, cont; | |
138 | ||
139 | for (cont = 0; fgets (line, sizeof (line), fp) != NULL;) | |
140 | { | |
141 | if ((cp = rindex (line, '\n')) != NULL) | |
142 | *cp = '\0'; /* strip the newline */ | |
143 | ||
144 | /* | |
145 | * Add the line to the value, at the end if this is a continuation | |
146 | * line; otherwise at the beginning, but only after any trailing | |
147 | * backslash is removed. | |
148 | */ | |
149 | vp = value; | |
150 | if (cont) | |
151 | vp += strlen (value); | |
152 | ||
153 | /* | |
154 | * See if the line we read is a continuation line, and strip the | |
155 | * backslash if so. | |
156 | */ | |
157 | len = strlen (line); | |
158 | if (len > 0) | |
159 | cp = &line[len - 1]; | |
160 | else | |
161 | cp = line; | |
162 | if (*cp == '\\') | |
163 | { | |
164 | cont = 1; | |
165 | *cp = '\0'; | |
166 | } | |
167 | else | |
168 | { | |
169 | cont = 0; | |
170 | } | |
171 | (void) strcpy (vp, line); | |
172 | if (value[0] == '#') | |
173 | continue; /* comment line */ | |
174 | vp = value; | |
175 | while (*vp && isspace (*vp)) | |
176 | vp++; | |
177 | if (*vp == '\0') | |
178 | continue; /* empty line */ | |
179 | ||
180 | /* | |
181 | * If this was not a continuation line, add the entry to the database | |
182 | */ | |
183 | if (!cont) | |
184 | { | |
185 | Node *p = getnode (); | |
186 | char *kp; | |
187 | ||
188 | kp = vp; | |
189 | while (*vp && !isspace (*vp)) | |
190 | vp++; | |
191 | *vp++ = '\0'; /* NULL terminate the key */ | |
192 | p->type = NDBMNODE; | |
193 | p->key = xstrdup (kp); | |
194 | while (*vp && isspace (*vp)) | |
195 | vp++; /* skip whitespace to value */ | |
196 | if (*vp == '\0') | |
197 | { | |
198 | error (0, 0, "warning: NULL value for key `%s'", p->key); | |
199 | freenode (p); | |
200 | continue; | |
201 | } | |
202 | p->data = xstrdup (vp); | |
203 | if (addnode (list, p) == -1) | |
204 | { | |
205 | error (0, 0, "duplicate key found for `%s'", p->key); | |
206 | freenode (p); | |
207 | } | |
208 | } | |
209 | } | |
210 | } | |
211 | ||
212 | #endif /* MY_NDBM */ |